Open hlship opened 6 years ago
If you don't need to worry about keeping the value, I think you can do something like:
with flux.to cell, 0.5, dy: 0
\ease "quintin"
\delay 0.05 * (cell.column - 8)
This might not work as expected because it stores the flux.to
value as a variable then applies the method calls to that rather than literally chaining them.
Is that a temporary work around, or a statement that the syntax I want will not / can not be implemented?
The syntax you suggested with \
at the beginning of the next line would conflict with the with
block syntax. We could implement this by having the \
be a trailing character on the proceeding line
@hlship It's not a workaround, it's how the language was designed. The syntax you were using is already implemented, but with something else. It might work for your use case though depending on what \delay()
affects - if it affects a value returned from \ease()
which is not a flux.to
value, then it won't work.
I'm just used to Clojure where everything is chaining operations (because all data is immutable). But I do like MoonScript, far more fluid, concise, and readable than standard Lua.
I did a bit of work in CoffeeScript a couple of years back, so this is familiar territory.
We could implement this by having the \ be a trailing character on the proceeding line
Suppose we're using some 'chainy' API like LuaLinq's one. This is an artifical example:
from(array)\ -- I know 'from' is a reserved word, but this is just an example
where((item) ->
item.startdate > date1 and item.startdate < date2)\
select((item) -> item.taskname)\
toArray!
Without these parentheses around arguments it could look weird. With them it looks more 'heavy' than Moonscript's parentheses-less style, but still more comfortable than Lua syntax. Would be a nice feature in Moonscript. Also, what should happen to indentation with each method call? There is no difference between 1st call and any other call, so it looks like it should either stay the same (then it's easy to not notice \ at the end of previous line) or increase at each call...
That's a good point @Penguinum about not being able to leave out parens with that style. Regarding white-space, since there's a character signifying the next line there doesn't need to be strict white-space, so I would expect people to indent
If that's of any interest, this had been an open topic in CoffeeScript 6 years ago ( https://github.com/jashkenas/coffeescript/issues/1407 ) though its fork Coco (https://github.com/satyr/coco/issues/64) and LiveScript added a space-before rule where a 'b' .c
is a('b').c
. This was also added to CoffeeScript a few years back: https://github.com/jashkenas/coffeescript/pull/3263.
Any update on this one? I hit on this when using argparse (https://github.com/mpeterv/argparse). That makes use of function chaining much like the python argpase. You can very quickly end up with cumbersome lines out of this when you add many options to a single argument. Would love an elegant solution to this one.
@lifeisafractal can you provide an example? Unfortunately chaining after-line is too close to the with
format but it'd be interesting to see if I could redo it with the with
syntax.
I'm pretty new to Moonscript, so it turns out in the case of argparse, with
is exactly what I wanted. This works because the argparse objects are mutable.
This long line:
install\option("-f --file", "file to install")\args(1)\count(1)\argname('UPDATE_FILE')\convert(io.open)
can become this using the with
statement which is arguably much more readable.
with install\option("-f --file", "file to install")
\args(1)
\count(1)
\argname('UPDATE_FILE')
\convert(io.open)
Where this falls down is when working on immutable objects like strings.
my_str = my_str\trim()\split('\n')
Is not functionally equivalent to
my_str = with my_str
\trim()
\split('\n')
Not really a big deal I guess because you can use more lines. IMHO this is a bit more verbose, but not the end of the world by any stretch.
my_str = my_str\trim()
my_str = my_str\split()
Just thinking out loud here, it might be cool to have another variant of with
where rather than applying each line in the block to the with
argument, it truly chains them. For the sake of argument let's call this chain
.
so:
my_str = " fOO\nbAr "
my_str = chain my_str
\lrim()
\rtrim()
\lower()
\split('n')
would emit the following Lua
local my_str = " fOO\nbAr "
do
local _chain_0 = my_str
_chain_0 = _chain_0:ltrim()
_chain_0 = _chain_0:rtrim()
_chain_0 = _chain_0:lower()
_chain_0 = _chain_0:split('\n')
my_str = _chain_0
end
This would replace the following (in my opinion) more verbose code.
my_str = " fOO\nbAr "
my_str = my_str\ltrim()
my_str = my_str\rtrim()
my_str = my_str\lower()
my_str = my_str\split('n')
This is just a half-baked thought so don't take it too seriously. Overall it's likely better to keep the language simpler and not add mountains of syntax sugar.
BTW chaining on multiple lines is possible if you leave method call on the line it should [currently] be but move arguments and closing parentheses on new line:
some_string = another_string\gsub(
"asdf", "qwer"
)\gsub(
"qwer", "asdf"
)\upper!
Kind of more ugly, but works.
Found this issue today when I was trying to use underscore.lua. Anyone else have any workarounds two years later? Normal lua supports multi-line chains, so it would be really nice if I could pull the same thing off in moonscript without temporary variables.
@ajusa told me to put it here, so here goes (discord thread)
wrap = =>
setmetatable {_val: @},
__index: (k) =>
(_, ...) ->
@_val=@_val[k] @_val, ...
unwrap = =>
@_val
_ = require 'underscore'
with wrap _{1, 2, 3, 4, -2, 3}
\chain!
\map => 2*@
\filter => @>3
\each => print @
a=unwrap with wrap _{1, 2, 3, 4, -2, 3}
\chain!
\map => 2*@
\filter => @>3
\value!
print table.concat a, '\t'
the wrap
function creates an object that automatically wraps methods and mutates its internal state. unwrap
just undoes it so you can collect it after the with
call without having to add another line.
note that this is an ugly hack and another way to do this would be way cleaner
I'd like to be able to chain method calls across line breaks. e.g.
But nothing I've found works. I'd be open to indenting the second and third lines.
Depending on indentation, I get
Compile error: Short-dot syntax must be called within a with block
orFailed to parse: [2] >> \ease("quintin")
.It works as expected if it is all one line, and there are no spaces before the backslashes.