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.)