Constraints patch - help?

classic Classic list List threaded Threaded
15 messages Options
Reply | Threaded
Open this post in threaded view
|

Constraints patch - help?

Asko Kauppi

I'm repeating the request for help, from people interested in getting function parameter, local var, and return value constraints to Lua.

The approach I'm taking is a patch, because:
- I'd like this feature to get _into_ Lua, instead of being a kludge add-on
   - performance should be made as good as possible

Current state of the patch is that all parsing is done (and works); constraint strings are placed in variable and function data structures in seemingly meaningful places.

What remains is ways to enforce the constraints at runtime. A group of people for discussing different alternatives would be useful, as bouncing something within a sole person's head is never the most creative approach.

We could use this list, but I'm afraid it's bound to get into teeny-weeny details pretty soon (= instantly). Once a working, tested concept patch is there, the list can be informed.

thanks,   :)
-asko

Reply | Threaded
Open this post in threaded view
|

Re: Constraints patch - help?

Mike Kreuzer-2
[hidden email] wrote:

I'm repeating the request for help, from people interested in getting function parameter, local var, and return value constraints to Lua.

[I missed this the first time around, and I'm probably being more than
unusually dense, so apologies in advance, but ...]

What's wrong with checking in the function, or after it's returned?  I
don't see the issue.

Regards,
Mike Kreuzer
www.mikekreuzer.com


Reply | Threaded
Open this post in threaded view
|

Re: Constraints patch - help? [what about "native" multimethod dispatch?]

Karel Tuma
In reply to this post by Asko Kauppi
hi,

what about multimethod dispatch based on types or even constraints,
lispers are constantly bragging about:

tab.do_something(num foo, num bar)
tab.do_something(string blah, num baz)

could be sugar for

tab.do_something_number_number(foo,bar)
tab.do_something_string_number(blah,baz)

and calling protocol:
tab[do_something.."_"..type(arg1).."_"..type(arg2)](arg1,arg2)

similiarly as for argument type constraints, this is partially implementable using
metatables, but not to the degree i'd call satisfactory.

this is not trivial, if not impossible, to implement into current
parser.

<lua_vs_lisp_rants>
but having this along with first-class value macros (could be
possibly implemented, though with more overhead than usual functions) would keep
lispers shut about lua just being "another half-implemented lisp derivative" :-P
</lua_vs_lisp_rants>

as for the syntax for value constraints - prefix or postfix syntax allowing usual lua
expressions would be cool:

function fun(s($==1 or $=="a"), n isnumber($))
	local s2 (isstring($) and #$>5) = somethingcool(s)
	return somethingboring(s,s2,n) isstring($)
end

or something similiar.

the idea is to make it as flexible as asserts(), yet
in-place, not to mention use of existing mechanisms in lua, rather
than introducing new ones.

personally i find value constraints a bit redundant (type constraints
would be subset of value constraints in lua), useful only for the
debugging stage - i'm the kind of keep-it-short type of person
(and when it breaks ... well then). if something may break
seriously, that's what pcall() is for.

by the way, will be the current constraints code available on
the svn soon? still rather cool patch to take a look/steal/bastardize :)

On Mon, Oct 23, 2006 at 09:45:43AM +0200, [hidden email] wrote:
> 
> I'm repeating the request for help, from people interested 
> in getting function parameter, local var, and return value 
> constraints to Lua.
> 
> The approach I'm taking is a patch, because:
>    - I'd like this feature to get _into_ Lua, instead of 
> being a kludge add-on
>    - performance should be made as good as possible
> 
> Current state of the patch is that all parsing is done 
> (and works); constraint strings are placed in variable and 
> function data structures in seemingly meaningful places.
> 
> What remains is ways to enforce the constraints at 
> runtime.  A group of people for discussing different 
> alternatives would be useful, as bouncing something within 
> a sole person's head is never the most creative approach.
> 
> We could use this list, but I'm afraid it's bound to get 
> into teeny-weeny details pretty soon (= instantly).  Once 
> a working, tested concept patch is there, the list can be 
> informed.
> 
> thanks,   :)
> -asko

Reply | Threaded
Open this post in threaded view
|

Re: Constraints patch - help? [what about "native" multimethod dispatch?]

David Given
Karel Tuma wrote:
[...]
> tab[do_something.."_"..type(arg1).."_"..type(arg2)](arg1,arg2)
[...]
> similiarly as for argument type constraints, this is partially implementable
using
> metatables, but not to the degree i'd call satisfactory.

Untested, but:

t = {}
setmetatable(t, t)
function t:__index(key)
	return function dispatch(...)
		local k = {key}
		for _, j in ipairs(arg) do
			k[#k+1] = type(j)
		end
		k = table.concat(k, "_")
		return rawget(self, k)(unpack(arg))
	end
end

Now, whenever you call a method k on t, it'll actually attempt to call
k_type1_type2_type3... instead. This strikes me as being rather simple code
--- why do you consider such an approach unsatisfactory?

I don't believe that such a thing belongs into the parser. Nobo

[...]
> function fun(s($==1 or $=="a"), n isnumber($))
> 	local s2 (isstring($) and #$>5) = somethingcool(s)
> 	return somethingboring(s,s2,n) isstring($)
> end

Again, what's the difference between this and:

function fun(s, n)
	assert((s==1 or s=="a") and isstring(n))

	local s2 = somethingcool(s)
	assert(isstring(s2) and (#s2 > 5))

	local r = somethingboring(s, s2, n)
	assert(isstring(r))
	return r
end

...? I find this considerably clearer to read, as well as not needing any new
features. It makes it explicit the order of processing, for example --- in
your example, the 'local' line has the assertions on the left of the
expression, where the return line puts them on the right, which isn't terribly
clear.

-- 
+- David Given --McQ-+ "There is one thing a man must do // Before his
|  [hidden email]    | life is done; // Write two lines in APL // And make
| ([hidden email]) | the buggers run."
+- www.cowlark.com --+ --- The Devil's DP Dictionary

Attachment: signature.asc
Description: OpenPGP digital signature

Reply | Threaded
Open this post in threaded view
|

Re: Constraints patch - help? [what about "native" multimethod dispatch?]

Karel Tuma
hello,

On Mon, Oct 23, 2006 at 03:34:44PM +0200, David Given wrote:
> Karel Tuma wrote:
> [...]
> > tab[do_something.."_"..type(arg1).."_"..type(arg2)](arg1,arg2)
> [...]
> > similiarly as for argument type constraints, this is partially implementable
> using
> > metatables, but not to the degree i'd call satisfactory.
> 
> Untested, but:
> 
> t = {}
> setmetatable(t, t)
> function t:__index(key)
> 	return function dispatch(...)
> 		local k = {key}
> 		for _, j in ipairs(arg) do
> 			k[#k+1] = type(j)
> 		end
> 		k = table.concat(k, "_")
> 		return rawget(self, k)(unpack(arg))
> 	end
> end

i'm using __index very similiar to yours.

the problem is you've to name your function like
function t.do_something_number_string(a,b) ... end
which is not much readable for some people.
... having sugar just for function t.do_something(number a, string b) .. end
would be more readable though.

> Now, whenever you call a method k on t, it'll actually attempt to call
> k_type1_type2_type3... instead. This strikes me as being rather simple code
> --- why do you consider such an approach unsatisfactory?

creating unique function closure for each function call.

> 
> I don't believe that such a thing belongs into the parser. Nobo

agreed

> [...]
> > function fun(s($==1 or $=="a"), n isnumber($))
> > 	local s2 (isstring($) and #$>5) = somethingcool(s)
> > 	return somethingboring(s,s2,n) isstring($)
> > end
> 
> Again, what's the difference between this and:
> 
> function fun(s, n)
> 	assert((s==1 or s=="a") and isstring(n))
> 
> 	local s2 = somethingcool(s)
> 	assert(isstring(s2) and (#s2 > 5))
> 
> 	local r = somethingboring(s, s2, n)
> 	assert(isstring(r))
> 	return r
> end

i'm fine with assert()'s too, my post was merely
bastardization-suggestion for asko.

> 
> ...? I find this considerably clearer to read, as well as not needing any new
> features. It makes it explicit the order of processing, for example --- in
> your example, the 'local' line has the assertions on the left of the
> expression, where the return line puts them on the right, which isn't terribly
> clear.

the posfix/prefix/infix does not really matter as it is very subjective
topic. the point was to allow in-place usage of existing syntax instead
of 'range' etc.

ps:
i love the way that lua is not only an extension
language, but also extremely extendible language - it's just fun to play
with lua internals. and i wish it'll stay that way, which is plain lua
being bare minimum with people sticking optional bloat to customize it
the way they like, a feature unseen in other scripting language,
simplicity with the spice of optional complexity is a true power of lua.

fear the day when the whole lexer/parser/codegen will be maintained in lua and
core C lua will be merely VM bytecode interpreter:
http://luaforge.net/projects/yueliang/
/* not likely to happen because lua is not that suitable for writing
 * self-compiler as ocaml is *g* */

//kt


Reply | Threaded
Open this post in threaded view
|

Re: Constraints patch - help?

Asko Kauppi
In reply to this post by Mike Kreuzer-2

I've done that, of course. :)

The issue is, in larger programs its really benefitial to have the _option_ of using type constraints on your variables, values, and return values. Doing them integrated with the syntax simply hides them more from the eye than doing 'assert' everywhere.

Perhaps people don't see the urge for this; I wouldn't either in smallish programs. But let's consider things s.a. svn 2.0 considering use of Lua (without them actually _knowing_ about the language beforehand!) as part of their core implementation. If I were doing such code, I'd like to have them checks!

-asko


Mike Kreuzer kirjoitti 23.10.2006 kello 12.32:

[hidden email] wrote:
I'm repeating the request for help, from people interested in getting function parameter, local var, and return value constraints to Lua.
[I missed this the first time around, and I'm probably being more than
unusually dense, so apologies in advance, but ...]

What's wrong with checking in the function, or after it's returned?  I
don't see the issue.

Regards,
Mike Kreuzer
www.mikekreuzer.com



Reply | Threaded
Open this post in threaded view
|

Re: Constraints patch - help? [what about "native" multimethod dispatch?]

Asko Kauppi
In reply to this post by Karel Tuma

Karel Tuma kirjoitti 23.10.2006 kello 15.54:

hi,

what about multimethod dispatch based on types or even constraints,
lispers are constantly bragging about:

I don't know much about Lisp-etc. - goo there are people, who do. :)

tab.do_something(num foo, num bar)
tab.do_something(string blah, num baz)

could be sugar for

tab.do_something_number_number(foo,bar)
tab.do_something_string_number(blah,baz)

and calling protocol:
tab[do_something.."_"..type(arg1).."_"..type(arg2)](arg1,arg2)

tab.do_something( foo :num_or_string, bar :num )

'num_or_string' is a fancy (probably customized) function living as 'assert.num_or_string'. The constraints mechanism is giving no precedence to built-in types, _any_ constraint names can be used and they cause the corresponding 'assert.*' function to be called (or an error if no such is defined).

An assertion function can also _change_ the type of the value passing through it; this is meaningful for cases s.a. string->num conversion to allow placing "20" in a variable/parameter taking in numeric values (this, of course, can be changed simply by redeclaring 'assert.number' :).

I'm wanting to place all this out for grabs, perhaps by the end of the week I can. I just know too little about inner-inner-level of Lua core, but... learning.


similiarly as for argument type constraints, this is partially implementable using
metatables, but not to the degree i'd call satisfactory.

For arguments are just variables, as are function parameters.


this is not trivial, if not impossible, to implement into current
parser.

<lua_vs_lisp_rants>
but having this along with first-class value macros (could be
possibly implemented, though with more overhead than usual functions) would keep lispers shut about lua just being "another half-implemented lisp derivative" :-P
</lua_vs_lisp_rants>

Dunno. I'd simply use cpp if I needed a macro language for Lua.


as for the syntax for value constraints - prefix or postfix syntax allowing usual lua
expressions would be cool:

function fun(s($==1 or $=="a"), n isnumber($))
	local s2 (isstring($) and #$>5) = somethingcool(s)
	return somethingboring(s,s2,n) isstring($)
end

or something similiar.

function fun( s:a_or_1, n:number ) :string
	local s2 :string_longer(5) = somethingcool(s)
	return somethingboring(s,s2,n)
end

This of course only shows it 'can be done'. No true Lua functions but yes, 'range(1,10)' --which is built-in-- and 'string_longer(5)' -- which is not-- are both meaningful and can be done. Actually, they're done.

Return type is best to be before body, since there may be multiple return statements (which all should adhere to the same constraints). Ugh. ;)


the idea is to make it as flexible as asserts(), yet
in-place, not to mention use of existing mechanisms in lua, rather
than introducing new ones.

personally i find value constraints a bit redundant (type constraints
would be subset of value constraints in lua), useful only for the
debugging stage - i'm the kind of keep-it-short type of person
(and when it breaks ... well then). if something may break
seriously, that's what pcall() is for.

It's all about "marking the edges of the road", a very useful thing in these dark Finnish evenings and mornings; perhaps that's why I am bringing this up...? :P In countries with more sunlight, you might see type bugs even without?? :)


by the way, will be the current constraints code available on
the svn soon? still rather cool patch to take a look/steal/ bastardize :)

That's what I'm asking. As to my habits, you need svn, then svn co svn://slugak.dyndns.org/public/lua-jacket/

If nothing more, please 'svn log' and 'svn update' to see my remarks and daily progress..... Is this exhibitionism, or what?!!

-asko



On Mon, Oct 23, 2006 at 09:45:43AM +0200, [hidden email] wrote:

I'm repeating the request for help, from people interested
in getting function parameter, local var, and return value
constraints to Lua.

The approach I'm taking is a patch, because:
   - I'd like this feature to get _into_ Lua, instead of
being a kludge add-on
   - performance should be made as good as possible

Current state of the patch is that all parsing is done
(and works); constraint strings are placed in variable and
function data structures in seemingly meaningful places.

What remains is ways to enforce the constraints at
runtime.  A group of people for discussing different
alternatives would be useful, as bouncing something within
a sole person's head is never the most creative approach.

We could use this list, but I'm afraid it's bound to get
into teeny-weeny details pretty soon (= instantly).  Once
a working, tested concept patch is there, the list can be
informed.

thanks,   :)
-asko


Reply | Threaded
Open this post in threaded view
|

Re: Constraints patch - help? [what about "native" multimethod dispatch?]

Asko Kauppi
In reply to this post by Karel Tuma

:) I'm having this idea of a lua-patches site, where you check the boxes (version, patches...) and it will spit you with a .tgz having all that! :)))))

Could be done.  Should?  hmm...


Karel Tuma kirjoitti 23.10.2006 kello 18.39:

ps:
i love the way that lua is not only an extension
language, but also extremely extendible language - it's just fun to play
with lua internals. and i wish it'll stay that way, which is plain lua
being bare minimum with people sticking optional bloat to customize it
the way they like, a feature unseen in other scripting language,
simplicity with the spice of optional complexity is a true power of lua.


Reply | Threaded
Open this post in threaded view
|

Re: Constraints patch - help?

Rici Lake-2
In reply to this post by Asko Kauppi

On 23-Oct-06, at 1:11 PM, Asko Kauppi wrote:

The issue is, in larger programs its really benefitial to have the _option_ of using type constraints on your variables, values, and return values. Doing them integrated with the syntax simply hides them more from the eye than doing 'assert' everywhere.

But why hide them? assert is a perfectly good way of making it clear what the function expects:

function extract(str, i, j)
  assert(isString(str))
  assert(isNumber(i) and i >  0 and i <= #str)
  assert(isNumber(j) and j >= i and j <= #str)

  local outside = str:sub(1, i) .. str:sub(j+1)
  local inside = str:sub(i, j)

  assert(#outside + #inside == #str)
  return inside, outside
end


Reply | Threaded
Open this post in threaded view
|

Re: Constraints patch - help?

Asko Kauppi

Tastes differ.

For local variables, because assert needs to be there N times, a constraint is given just once and applies throughout that variable's lifespan (checked at every assignment).

I am a heavy user of assert, or ASSUME as I like to alias it. That's not going anywhere, as if I were in position to change the language we love, to begin with...



Rici Lake kirjoitti 23.10.2006 kello 21.33:


On 23-Oct-06, at 1:11 PM, Asko Kauppi wrote:

The issue is, in larger programs its really benefitial to have the _option_ of using type constraints on your variables, values, and return values. Doing them integrated with the syntax simply hides them more from the eye than doing 'assert' everywhere.

But why hide them? assert is a perfectly good way of making it clear what the function expects:

function extract(str, i, j)
  assert(isString(str))
  assert(isNumber(i) and i >  0 and i <= #str)
  assert(isNumber(j) and j >= i and j <= #str)

  local outside = str:sub(1, i) .. str:sub(j+1)
  local inside = str:sub(i, j)

  assert(#outside + #inside == #str)
  return inside, outside
end



Reply | Threaded
Open this post in threaded view
|

Lisp-style Macros (was Re: Constraints patch - help? [what about "native" multimethoddispatch?])

Paul Hudson-2
In reply to this post by Asko Kauppi

Dunno. I'd simply use cpp if I needed a macro language for Lua.

Cpp isn't even close to Lisp macros. I'm not sure Lisp-style macros worth adding to Lua (and it's difficult to think how they could be, given Lua's complex syntax relative to Lisp's), but they are nice...




Reply | Threaded
Open this post in threaded view
|

Re: Constraints patch - help?

Doug Currie
In reply to this post by Asko Kauppi
Monday, October 23, 2006, 2:38:28 PM, Asko Kauppi wrote:

> Tastes differ.

> [...]

> I am a heavy user of assert, or ASSUME as I like to alias it.

I just happened to be looking at Extended Static Checking
http://citeseer.ist.psu.edu/detlefs98extended.html where ASSUME means
something quite different! See section 11, "The tarpit of creeping
aspirations."

e

-- 
Doug Currie
Londonderry, NH


Reply | Threaded
Open this post in threaded view
|

RE: Constraints patch - help?

Ram Firestone
In reply to this post by Asko Kauppi

> -----Original Message-----
> From: [hidden email] [[hidden email]] On Behalf Of
> Asko Kauppi
> Sent: Monday, October 23, 2006 11:38 AM
> To: Lua list
> Subject: Re: Constraints patch - help?
> 
> 
> Tastes differ.
> 
> For local variables, because assert needs to be there N times, a
> constraint is given just once and applies throughout that variable's
> lifespan (checked at every assignment).
> 

However this starts to make the language into a strongly typed language which Lua is not meant to be. IMO one of great things about
Lua is it doesn't try to do too much (read Java).  I use Lua primarily as an extension language at which it greatly excels. For this
purpose, explicit strong typing might be considered overkill. Even if it were optional, the required changes to the language may
hurt performance which I think is a bad trade off. 

Having an optional type check at function call or return time is a more modest proposal but I'm still not convinced it is really
needed.




Reply | Threaded
Open this post in threaded view
|

Re: Constraints patch - help? [CGI-based patch merging repository]

Karel Tuma
In reply to this post by Asko Kauppi
hey,

On Mon, Oct 23, 2006 at 08:32:02PM +0200, Asko Kauppi wrote:
> 
> :)  I'm having this idea of a lua-patches site, where you check the  
> boxes (version, patches...) and it will spit you with a .tgz having  
> all that!  :)))))
> 
> Could be done.  Should?  hmm...

that's such a crazy idea it might not be a bad idea after all ;-)
http://blua.leet.cz/ with checkboxes now ;-)

patches may be included as long they're properly unifdef-friendly #ifdefed

people who like to fool around with cgi scripts can try their luck
after deciphering http://blua.leet.cz/cgi-bin/bastardize.txt :P

it's a bit resource-intensive and dunno if it works with all browsers
(tested with opera & links) but guess it will do for the time being.


Reply | Threaded
Open this post in threaded view
|

Re: Constraints patch - help?

Ivan Kolev-2
In reply to this post by Asko Kauppi
From: Mike Kreuzer <[hidden email]>

What's wrong with checking in the function, or after it's returned?  I
don't see the issue.

From: David Given <[hidden email]>

Now, whenever you call a method k on t, it'll actually attempt to call
k_type1_type2_type3... instead. This strikes me as being rather simple code
--- why do you consider such an approach unsatisfactory?

I don't believe that such a thing belongs into the parser. Nobo
...
...? I find this considerably clearer to read, as well as not needing any new
features. It makes it explicit the order of processing, for example --- in
your example, the 'local' line has the assertions on the left of the
expression, where the return line puts them on the right, which isn't terribly
clear.

Agreed. I only see a real benefit of such patch if it checked the types at compile time, plus (optionally) at runtime (for the cases when a value with "any" type is bound to a parameter with a specified type).

Ivan Kolev