Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

What is the idiomatic way to read from the standard input? #1881

Open
nameOfUser0236 opened this issue Jan 18, 2025 · 3 comments
Open

What is the idiomatic way to read from the standard input? #1881

nameOfUser0236 opened this issue Jan 18, 2025 · 3 comments

Comments

@nameOfUser0236
Copy link

I have recently started learning the language, and I am trying to figure out how I can write functions that work well in pipelines. Writing to pipes is fairly obvious (just use echo/write for bytes and put for values), however, reading from them is less so.

@iandol
Copy link
Contributor

iandol commented Jan 19, 2025

Some elvish functions support pipelines directly, but other's don't, and I also find this pretty confusing. But although the names are totally not intuitive to me, all and one are commands which can read fromthe pipe and push out values, so for example:

fn elvish-updates { |&n=10|
	var sep = "\n----------------------------"
	curl "https://api.github.com/repos/elves/elvish/commits?per_page="$n |
	all (from-json) |
	each {|issue| echo $sep; echo (styled $issue[sha][0..12]" "$issue[commit][committer][date] bold)":\n" (styled (re:replace "\n" "  " $issue[commit][message]) yellow) }
}

from-json reads byte output, and from my confused understanding all allows this to be converted to a value list. Basically if you remove all this pipeline fails and with it present it works. This is probably best explained by https://elv.sh/learn/pipelines-and-io.html#working-with-both-bytes-and-values I find it hard to unlearn the all from other languages being a logic operation.

This is the impenetrable first sentence description of all:

Takes value inputs, and outputs those values unchanged.

https://elv.sh/ref/builtin.html#all

I personally don't really understand that sentence. If from-json outputs values, this suggests all will make no changes, and yet it clearly does in the example above. Anyway, I just try combinations of all and one till something works.

@hanche
Copy link
Contributor

hanche commented Jan 23, 2025

The very short answer to the question about all lies in the end of its longish description.
The bit about being the the identity function for the value channel is true when all is called without an argument. If it's called with an argument, it “explodes” that argument into its individual components, and outputs them separately:

⬥ all [one two three]
⮕ one
⮕ two
⮕ three
⬥ all abc
⮕ a
⮕ b
⮕ c

@hanche
Copy link
Contributor

hanche commented Jan 23, 2025

Anyway, on reading from a pipe: It's tricky if the pipe contains a mixture of bytes and values. In general, I think it's best to avoid that. To read all the bytes from a pipe, there is slurp. It will output the byte input as a (possibly giant) string, on the value channel, whiere you can capture it. A function like each will read byte inputs a line at a time and call its function argument on each one in turn. It will include values too. But if you mix values and bytes on the channel, you're not guaranteed that each or all will process them in the order they were written. This is one reason why mixing bytes and values is often a bad idea.

All this takes a bit of getting used to. I made quite an impressive number of mistakes when I was learning elvish, many of them silly in retrospect.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: ❓Triage
Development

No branches or pull requests

3 participants