[ruby-optimization] more macros thoughts

10 views
Skip to first unread message

rogerdpack

unread,
May 10, 2010, 2:58:10 PM5/10/10
to ruby optimization
The other day I was contemplating something like Pythonic imports,
like

maybe "special comment" a file, like

# coding: UTF-8; from IO import select

(then all select calls get translated to IO.select)

That might be nice.

Another thought was something like

# coding: UTF-8; use BigDecimal instead of Float

(automatically translates all float literals to
BigDecimal.new("float"))

or maybe some way to run ruby like that, like

$ ruby_wrapper --use-big-decimal filename.rb (same thing--somehow pre-
parses all ruby files it later requires to use BigDecimal instead of
float or what not).

Hmm...just mulling this over...

ref: http://www.ruby-forum.com/topic/208222#new
-rp

Caleb Clausen

unread,
May 11, 2010, 3:43:04 AM5/11/10
to ruby-opt...@googlegroups.com
rogerdpack wrote:
> The other day I was contemplating something like Pythonic imports,
> like
>
> maybe "special comment" a file, like
>
> # coding: UTF-8; from IO import select
>
> (then all select calls get translated to IO.select)
>
> That might be nice.

This probably should be possible, tho maybe not with exactly python's
syntax. How about this instead:

import IO.select

I don't understand why you want to make this part of the magic encoding
comment, tho. Among other things, that's harder. It should be in a
line(s) by itself. Like in python.

Python's import has file-level scope, as I recall. That's a little hard
to emulate, so I didn't try below.

I wrote up an import macro which takes multiple arguments, allows
importing both class and instance methods, and handles method_missing.
It also requires some features which don't exist yet (sigh). There's the
^* operator again, this is like the 4th time I've wanted it. And ^&
which is related, but I haven't seen before. Not sure if CallNode#colon
exists or not yet either:

macro import imports
SequenceNode[ imports.map{|import|
forwards_to,name=*import
if !import.colon
:(
def (^name)(*args,&block)
extend ^forwards_to
^(:(return self.send(*args,&block)) if name=='method_missing')
self.(^name)(*args,&block)
end
)
else
:(
macro (^import.name)(*args)
(^import.receiver).^(import.name)(^*args,^&yield)
end
)
end
}]
end

This macro has a near-equivalent that can be written using plain eval.
Gotta stuff all your arguments into string(s), tho:

def import imports
eval imports.map{|import|
all,forwards_to,kind,name=import.match(/\A(.*)(\.|::)(.*)\z/)
if kind=="."
%{
def #{name}(*args,&block)
extend #{forwards_to}
#{'return self.send(*args,&block)' if name=='method_missing'}
self.#{name}(*args,&block)
end
}
else
%{
def #{name}(*args,&block)
#{forwards_to}.#{name}(*args,&block)
end
}
end
}.to_s
end

That second one might actually work.

I got real excited as I was writing this... maybe this would work as an
implementation of selector namespaces? Well, for simple cases, yes, but
it won't allow the dynamic creation of method chains in AOP style like
it should, so not really. :/

Also, I just remembered SingleForwardable#def_singleton_delegator and
Forwardable#def_instance_delegator from stdlib, they do basically the
same thing. Klunkier syntax, tho.

> Another thought was something like
>
> # coding: UTF-8; use BigDecimal instead of Float
>
> (automatically translates all float literals to
> BigDecimal.new("float"))

This is well beyond the scope of what macros can do now. I can't really
do macro magic on any syntax node which doesn't already look like a
method call. Float literals definitely don't qualify.

A future feature (up-pointers in syntax trees) might enable this kind of
thing.

I think it's possible to write a parse tree rewriter which just uses
RedParse, not RubyMacros and does what you want. It would be fairly
simple, but I'm not gonna try it, because I don't see a significant need
for this particular feature. Feel free to try to persuade me otherwise
if you desire.

It is easy enough right now to create a macro which works like this:

1.2345.bd # => BigDecimal.new("1.2345")

I think the implementation is something like this:

macro bd #also untested
:(BigDecimal.new(^self.val.to_s))
end

(This probably requires edge code. And may not be as accurate as you'd
like, since the number is converted to float representation then back to
a string. Ideally, you'd get the plain string representation out of the
LiteralNode using ^self.as_str or something, but that's not available
right now... I really should change that.)

Roger Pack

unread,
May 11, 2010, 11:17:10 AM5/11/10
to ruby-opt...@googlegroups.com
Oh wow nice. Now that you mention it that's a great idea to have the
import command just expand to define a caller (delegate) to the real
method. I like it...

I like the BD rewriter stuff, too...I think what you described
"should" work, with all versions of Ruby...I think. I wonder if
anybody would actually want to use such a beast...maybe if it
defaulted to rational... :)

My next two projects are going to be
1) get the endless ruby thing going again. Just fer fun.

2) write a method helper so you can call

def go(x, y)
end

like

xxx.go_x(3).y(4)

or something like that :)

Wish me luck.

Thanks!
[rp]

rogerdpack

unread,
May 11, 2010, 11:36:22 AM5/11/10
to ruby optimization
I remembered what my other wish list item was for rubymacros...it was
something like allowing for

a(3)(4)(5)

(convert it to a(3).(4).(5) since apparently Ruby "can't do that"
currently).

I.e. something that looks more like method composition.

It's faulted by some people as a drawback that Ruby can't do this
currently (I don't know why it can't--can't parse it?).


a(3).(4).(5)
is ok in 1.9.1 though.

Thoughts?
-rp

Caleb Clausen

unread,
May 11, 2010, 12:58:11 PM5/11/10
to ruby-opt...@googlegroups.com
Roger Pack wrote:
> Oh wow nice. Now that you mention it that's a great idea to have the
> import command just expand to define a caller (delegate) to the real
> method. I like it...

I wish it were real selector namespaces... maybe there is a way, I keep
thinking there should be a 'good enough' static version of that concept.

> I like the BD rewriter stuff, too...I think what you described
> "should" work, with all versions of Ruby...I think. I wonder if
> anybody would actually want to use such a beast...maybe if it
> defaulted to rational... :)

It just occurred to me that one could define bd as a method on Float as
well. (I think a macro is prettier, tho.)

> My next two projects are going to be
> 1) get the endless ruby thing going again. Just fer fun.

Lemme know if you need help with that. I may well have changed something
in RubyLexer which causes this to break.

> 2) write a method helper so you can call
>
> def go(x, y)
> end
>
> like
>
> xxx.go_x(3).y(4)
>
> or something like that :)

I didn't understand this. But don't worry too much about it.

> Wish me luck.

Good Luck!

> I remembered what my other wish list item was for rubymacros...it was
> something like allowing for
>
> a(3)(4)(5)
>
> (convert it to a(3).(4).(5) since apparently Ruby "can't do that"
> currently).

Again, this is beyond what macros are capable of. Now you're talking
about some fairly serious parser hackery. (It'll create ambiguities with
some of the things I permit in RubyMacros as well. I'm not sure if
that's a serious worry or not.)

Here's another way that works out of the box in all versions of ruby.
I've always felt its good enough:

a(3)[4][5]

> I.e. something that looks more like method composition.
>
> It's faulted by some people as a drawback that Ruby can't do this
> currently (I don't know why it can't--can't parse it?).

Yes, well, "some people" like writing in javascript or python. There's
no accounting for taste. ;)

> a(3).(4).(5)
> is ok in 1.9.1 though.

I've never liked that syntax much. But I'm prejudiced.

Roger Pack

unread,
May 11, 2010, 1:33:28 PM5/11/10
to ruby-opt...@googlegroups.com
> It just occurred to me that one could define bd as a method on Float as
> well. (I think a macro is prettier, tho.)

That's a good idea. hmm...

Caleb Clausen

unread,
May 11, 2010, 2:49:51 PM5/11/10
to ruby-opt...@googlegroups.com
As either a macro or a method, bd is going to be a lot more accurate
after marc-andre's fix for Float#to_s from last night. I sure hope that
get's backported to 1.8.6.

Roger Pack

unread,
May 11, 2010, 3:11:36 PM5/11/10
to ruby-opt...@googlegroups.com
> As either a macro or a method, bd is going to be a lot more accurate
> after marc-andre's fix for Float#to_s from last night. I sure hope that
> get's backported to 1.8.6.

Good call. I suppose those methods would work quite well with Float's
new #to_s in 1.9.2 (but they could recreate it themselves, too, if
desired, for 1.8, for example).
-rp

rogerdpack

unread,
May 13, 2010, 2:43:51 PM5/13/10
to ruby optimization
> Also, I just remembered SingleForwardable#def_singleton_delegator and
> Forwardable#def_instance_delegator from stdlib, they do basically the
> same thing. Klunkier syntax, tho.

Forwardable does seem to work--in its kludgey way...

I guess in reality what python's import statements are are basically
"magic rewrite comments" for the file.

> I got real excited as I was writing this... maybe this would work as an
> implementation of selector namespaces?

Talking of namespaces reminds me of the "with" of rewrite.

http://rewrite.rubyforge.org/

wonder if that direction has any potential, or why it didn't seem to
pick up in popularity...

-rp

rogerdpack

unread,
May 13, 2010, 2:49:44 PM5/13/10
to ruby optimization

> I guess in reality what python's import statements are are basically
> "magic rewrite comments" for the file.

I keep thinking that what I want is something like
# coding: utf-8
# macro_file: big_macro_file.rb
# use andand, simple, IO.select

def go
simple(1,2)
select(a,b,c)
end

or what not...but I haven't looked at it too closely :P

-rp

Caleb Clausen

unread,
May 13, 2010, 6:23:09 PM5/13/10
to ruby-opt...@googlegroups.com
rogerdpack wrote:
>> Also, I just remembered SingleForwardable#def_singleton_delegator and
>> Forwardable#def_instance_delegator from stdlib, they do basically the
>> same thing. Klunkier syntax, tho.
>
> Forwardable does seem to work--in its kludgey way...

Feel free to use the one I wrote instead :)

>
> I guess in reality what python's import statements are are basically
> "magic rewrite comments" for the file.
>
>> I got real excited as I was writing this... maybe this would work as an
>> implementation of selector namespaces?
>
> Talking of namespaces reminds me of the "with" of rewrite.
>
> http://rewrite.rubyforge.org/
>
> wonder if that direction has any potential, or why it didn't seem to
> pick up in popularity...

Reg's with always felt to me kind of like lisp's let... a scoping
mechanism without any other semantics to it.

It always seemed to me the right way would be to use ruby's existing
scoping mechanisms (class, module, def) and attach some new semantics to
them. Maybe like this:

class Foo
Macro.import Bar.baz
#imports the baz macro defined in namespace Bar into Foo

end


Caleb Clausen

unread,
May 13, 2010, 6:23:21 PM5/13/10
to ruby-opt...@googlegroups.com
how about:

# coding: utf-8
Polyglot.dialect :macro
Macro.require "big_macro_file.rb"
Macro.import andand, simple, IO.select

def go
simple(1,2)
select(a,b,c)
end

That's the syntax I'm aiming for. (Why do you keep wanting to do stuff
in comments?)

Roger Pack

unread,
May 19, 2010, 3:22:56 PM5/19/10
to ruby-opt...@googlegroups.com
> # coding: utf-8
> Polyglot.dialect :macro
> Macro.require "big_macro_file.rb"
> Macro.import andand, simple, IO.select

Yeah something like that would work. I would like to something like
# coding: utf-8
Macro.defaults [assumes that sometime previous you have setup "global
macros" or what not...]

-r=

Caleb Clausen

unread,
May 19, 2010, 4:45:49 PM5/19/10
to ruby-opt...@googlegroups.com
You mean, I guess, that 'Macro.defaults' will be some kind of shorthand
for the other 3 lines? Let me think about how to do that... the problem
is that 'Polyglot.dialect :macro' is actually a special magical
directive, tho it appears to be a method call.....

It is a lot to have to type at the top of every file. There ought to be
a way to make it shorter, I agree with that.
Reply all
Reply to author
Forward
0 new messages