[ANN] GSL Shell new beta release with anti-gran graphics module

classic Classic list List threaded Threaded
126 messages Options
1 ... 4567
Reply | Threaded
Open this post in threaded view
|

Re: Short function definition syntax; thoughts on Lua

Mark Hamburg
On Dec 7, 2009, at 12:03 AM, Juris Kalnins wrote:

>> 2. Expression trees
>>
>> If one wants to get really compact, then we could actually allow function construction at compile time at least for single argument functions. For example, $ isn't currently used as a token, so consider:
>>
>> $ would be defined as function( x ) return x end
>> $ * $ would be defined as function( x ) return x * x end
>> $ + 1 would be defined as function( x ) return x + 1 end
>> etc
>
> Nice idea, but Super hard to specify correctly. What is g(x + f($ * $ + 1)):
>
> g(x + f(function (_) return _ end + function (_) return _ end))
> g(x + f(function (_) return _ * _ end + 1))
> g(x + f(function (_) return _ * _ + 1 end))
> g(x + function (_) return f(_ * _ + 1) end)
> g(function (_) return x + f(_ * _ + 1) end)

Good point. I was going to supply the answer:

        function( _ ) return g( x + f( _ * _ + 1 ) ) end

This was based on a rule where these percolated up the tree as far as possible. That, however, makes these very difficult to pass as arguments.

> ?
> Plus, you have to make parser backtrack arbitrarily far upon encountering '$'.
> Currently it pretty much can emit bytecode as it goes over expression.

It's still amenable to recursive descent parsing and on the fly code generation, but there is probably a lot more work that has to be done in postfix order rather than prefix order and/or a second pass over the expression tree. So, yes, it complicates the compiler a bit (or considerably depending on how one views the construction and tear down of temporary syntax trees as part of the process).

But I think it's the complexity of getting the rules right rather than the complexity of implementation that really kills this approach.

Mark

P.S. LINQ makes this work in C# by using the static type rules to figure out where an expression tree is appropriate. That said, the static typing and extension mechanism in LINQ  doesn't work as well for dynamically extensible libraries precisely because it wants to resolve so much at compile time.

Reply | Threaded
Open this post in threaded view
|

Re: Re[2]: code density -- was:[ANN] GSL Shell...

Greg Fitzgerald
In reply to this post by steve donovan
On Sat, Dec 5, 2009, steve donovan wrote:
> Most of us like to read from left to right, as a chain of operations.
> Functional people have a larger stack than most, so they're used to
> everything being prefix ;)
> ...
> numbers:filter(odd):map(square)

Functional programmers read left to right too.  The difference is
functional programmers read from a "top-down" perspective, whereas
imperative programmers read "bottom-up".  Imperative programmers often
think of a program as a chain of commands that manipulate values.  A
functional programmer thinks of a program as the composition of
smaller programs.

bottom-up interpretation:
   Start with a list of numbers, filter the odd values, and with the
list of odds, square each value.

top-down interpretation:
   square each value of a list of odds

and so the Haskell programmer would write:
   map square . filter odd

I find bottom-up easier to write and top-down easier to read and
understand.  When reading programs in the top-down style, you don't
concern yourself with the details until you have a high-level
understanding of the intent of the program.  In Haskell, I frequently
write programs bottom-up and then factor them until they are top-down.
 The top-down program tends to be a better form for further factoring,
because as soon as the code is point-free, you see all the places
where your code is coincidentally a perfect match with library
definitions.  You then swap out your own code with calls to the
library code, and go home early because you don't have to add any
documentation or tests!  :-)

Bird's Sudoku solver is an outstanding example of a program that is
easy to learn and understand because it is written in the top-down
style and in point-free notation:

http://www.cs.tufts.edu/~nr/comp150fp/archive/richard-bird/sudoku.pdf

-Greg
Reply | Threaded
Open this post in threaded view
|

Re: Short function definition syntax; thoughts on Lua (was Re: [ANN] GSL Shell new beta release...)

Jerome Vuarand
In reply to this post by David Given
2009/12/6 David Given <[hidden email]>:
> Jerome Vuarand wrote:
> [...]
>> local f = y[[ x + y with x, y ]]
>
> This collides with long-string syntax (looks like a function call to y
> with a single string parameter).

That because it was precisely a proposal to implement it with current
unmodified Lua.
Reply | Threaded
Open this post in threaded view
|

Re: Short function definition syntax; thoughts on Lua (was Re: [ANN] GSL Shell new beta release...)

Gregg Reynolds-2
In reply to this post by Luiz Henrique de Figueiredo
On Fri, Dec 4, 2009 at 4:12 AM, Luiz Henrique de Figueiredo <[hidden email]> wrote:
> But there is a middle way; say there was a new keyword 'lambda', so
> that we can say lambda(arglist) expr, then a token filter could easily
> transform |x| into lambda(x).

Why 'lambda' when 'function' exists and works just as well?

Sorry I'm late to the party, but if the goal is to have an ultra-concise syntax for short one-off nameless functions, why bother naming arguments?  If 'lambda' (or 'function' or whatever) serves in combination with named parameters to name a function, wouldn't it be possible dispense with even that by just nominating a distinguished symbol to reference actual arguments?  E.g. underscore:

sizes = names.map {_.gsub("%A", "").lower}

Inspired obviously by pattern matching syntax.  I have no idea if this would be doable in Lua but as a syntax it seems to fit the bill for short functions - easy to type and read.  Multiple args could be handled by indexing, _[1], etc.

-gregg
Reply | Threaded
Open this post in threaded view
|

Re: Short function definition syntax; thoughts on Lua (was Re: [ANN] GSL Shell new beta release...)

steve donovan
On Wed, Dec 9, 2009 at 7:03 PM, Gregg Reynolds <[hidden email]> wrote:
>
> sizes = names.map {_.gsub("%A", "").lower}

It's tempting (Scala has a similar notation) but alas, underscore is
just an ordinary variable, which is comnonly used when you want to
throw away a value.   And if you consider tonumber(_) you see that the
parser has to do a lot of work to mark these expressions as actually
being functions.

Although it does make a nice notation for 'string lambdas', if you
don't mind quoting your short functions.

map '_:gsub("%A","):lower()'

In Penlight we used placeholder variables, so functions like map would
take expressions like _1+1 and _1*_2, which was inspired by the C++
Boost libraries.

steve d.
Reply | Threaded
Open this post in threaded view
|

Re: Short function definition syntax; thoughts on Lua (was Re: [ANN] GSL Shell new beta release...)

Javier Guerra Giraldez
In reply to this post by Jerome Vuarand
Jerome Vuarand wrote:
> A close form could already be implemented, without upvalues though:
>
> local f = y[[ x + y with x, y ]]

several times, i've wanted to generate functions like this.  usually not for the short 'lambda' syntax; but for simple DSLs

unfortunately, the no-upvalues limitation makes it not-so-useful.  it would be really great if there was a way to make the 'load()' or 'loadstring()' functions create full closures.  I guess the security implications are terrible, maybe can be mitigated by specifying a list of valid upvalue names?

but in theory it shouldn't be so hard... after all, the Lua core manages to create closures, surely its possible to add some extra function to do it from Lua's control.

reading the source, it seems that the important function is luaF_newLclosure(), which returns (in some structures too novel to me) the list of upvalues, to be defined by the calling function.  it's called at two points: on ldo.c and lvm.c.  the first one seems to be only for defining 'main chunks', so the upvalues are all defined as 'new'; while the second one is used to create function objects from the compiled code, and the upvalues are 'linked' to local variables or upvalues to the enclosing function.

maybe somebody more familiar with the deep guts of Lua could answer if it's doable to create a new 'loadclosure()' function that works more like the call from lvm.c, but reads from some given text, like on ldo.c ?

--
Javier
1 ... 4567