5 ms·
That was awesome, thanks for explaining that for us. It makes a lot of sense the way you explain it, and I quickly got the idea that you can make some powerful
by tinco 12y ago
That was awesome, thanks for explaining that for us. It makes a lot of sense the way you explain it, and I quickly got the idea that you can make some powerful expressions this way.
The smooth creation of lists is I think one of the most important language features higher level languages have over lower level languages like C.
Just this thing:
c::a$"\n"
That's all I needed to be convinced that modern languages should have similar view constructs. In ruby it'd be:
c = a.map.with_index{|a,i| a == "\n" ? i : nil }.reject{|i| i.nil? }
Quite a mouthful, mainly because Ruby lacks a neat way to do '$'. But doing the same thing in C would really be awkward, and likely not as efficient unless you have some fancy code for building enumerators in C.
- MichaelGG 12y agoCertainly you could wrap up the $ operator into some Ruby method?
- tree_of_item 12y agoYes, Ruby is Turing complete, but that's missing the point. The value K provides is the collection of operators like `$` that implement a high level language for the sorts of problems K programmers face. If you went through and implemented all of those operators in Ruby and only used those instead of things like loops, your code would be "unreadable" to the standard Ruby programmer; essentially you'd be programming in a different language.
- tinco 12y agoSure, simply do: module Enumerable def dollar(c) map.with_index{|a,i| a == c ? i : nil }.reject{|i| i.nil? } end end And then you could do: c = a.dollar("\n") There is of course a reason this dollar method is not a part of the standard library. Its name makes no sense and it's oddly specific, how often would you want the indexes of matches to a character? Most modern languages don't like to work with indexes a lot, and in my day to day work I don't need indexes very frequently either. This I guess is just a thing that these finance/apl people do more often, so they have a specialized standard library. (So when I said 'a neat way to do $' I meant it has no find_all_with_index method, which would make my implementation much cleaner)
- Widdershin 12y agoRegarding find_all_with_index, you can do: .find_all.with_index { |item, index| ... }
- dragonwriter 12y agoexcept .find_all.with_index passes the index to the predicate block, but still only returns a view of the matching elements from the list. What I think is being sought is more like: module Enumerable def find_indices each.with_index .find_all {|x,_| yield x} .map {|_,y| y} end end
- minor_nitwit 12y agothat seems overly complicated for ruby if a is a file. c = []; a.lines{c << a.pos} As far as $, you may know it from Regex as the new line indicator.
- geocar 12y agoa is a mapped string. You could do: c=[];n=0;a.lines{|x|c<<(n+=x.size)-1} but $"\n" wasn't special, and this allocates tons of memory. tinco's implementation is much closer to what k is actually doing.
- geocar 12y agoThe view automatically gets updated whenever a gets updated. Every time you change a (directly or indirectly), then c will automatically get updated. Doing this generally in Ruby I think is impossible, but you might be able to get close if all your objects are based on ActiveModel::Dirty
- dragonwriter 12y ago> Doing this generally in Ruby I think is impossible Not so much. At least with views over most Enumerables, its quite possible in Ruby -- that's the whole reason that Enumerable::Lazy exists. The existing File class doesn't quite support it because of the way its iterators are implemented (particularly, they are one way) but the class is easily extended to allow it, e.g.: class RewindFile < File def each rewind each_char {|x| yield x} end end Then you can create a synced view that has the character positions of the newlines in a file like this: a = RewindFile.new "myfile.txt" c = a.lazy.each .with_index .find_all {|x,_| x=="\n"} .map {|_,y| y}
- geocar 12y agoIf I go `a=whatever` or `a[42]=whatever`, then `c` will not get updated if I have already consumed those values; I still need to "reset" c every time I update a.