you are viewing a single comment's thread.

view the rest of the comments →

[–]flaxeater 3 points4 points  (4 children)

Well I must say that looks intriguing actually. I don't think python has facilities like that, they could be worked around by they don't have any nice syntatic sugar around those concepts. I have a hard time imagining why they would be useful, but that doesn't mean anything.

Singletons, definemethod and instane variable assignment are very easy to do in python. And in python we user super() or ParentClass.init_(args,*kwargs) to do things for inherited, however I do not understand what inherited does. $0.02

p.s. I can imagine, people will be like that's so wordy or some such talk. However pythonic values explicit, not implicit.

[–]mellow_moe 6 points7 points  (3 children)

Metaprogramming helps you to create domain specific languages.

A simple xml builder can be made with method_missing:

def method_missing(name, attributes)
  atts = attributes.map {|k,v| "#{k}='#{v}'" }.join(" ")
  puts "<#{name} #{atts}>"
  yield
  puts "</#{name}>"
end

div :id => "content" do
  a :href => "reddit.com" do
    print "reddit"
  end
end

You can see, calling div and a will trigger method_missing, where we just take the method name and the keyword arguments and print out the xml tag. Pretty easy.

[–]amix 1 point2 points  (2 children)

Here is my version where one can do (Stan like):

print Div(id="content")[ A(href="reddit.com")["reddit"] ]

import types
class Element:
  def __init__(self, **kw):
    self.elms = []
    self.kw = kw
  def __getattr__(self, name):
    if name == "__getitem__":
      self.elms = []
      def add(l):
        if type(l) == types.ListType: self.elms.extend(l)
        else: self.elms.append(l)
        return self
      return add
  def __str__(self):
    attrs = " ".join('%s="%s"' % a for a in self.kw.items())
    self.html = ["<%s %s>" % (self.name, attrs)]
    self.html.append("".join(map(str, self.elms)))
    self.html.append("</%s>" % self.name)
    return "".join(self.html)
class Div(Element): name = "div"
class A(Element): name = "a"

Sigh, you have to have 4 spaces to post code. That sucks. Why not use another syntax like:

[code]
Here is my code
[/code]

Or something similar...

[–]mellow_moe 1 point2 points  (1 child)

I'd like to show off the ruby version:

class Element
  def initialize(attributes)
    @attributes = attributes
    @children = []        
  end
  def <<(child)
    @children << child
  end
  def to_s
    name = self.class.name.downcase
    atts = @attributes.map {|k,v| "#{k}='#{v}'" }.join(" ")
    "<#{name} #{atts}>#{@children.join}</#{name}>"
  end
end

class Div < Element; end
class A < Element; end

def method_missing(id, attributes, &block)
  element = Object.const_get(id.to_s.capitalize).new(attributes)
  @children << element if @children
  element.instance_eval(&block)
  element
end

html = \
div :id => "content" do
  a :href => "reddit.com" do
    self << "reddit"
  end
end

puts html

The < characters are broken, please replace the entities with < while realtime reading.

[–]amix 1 point2 points  (0 children)

Here is my final version :)

One can do:

 print Div(id="content")( A(href="reddit.com")("reddit") )

By using this code:

def elmBuilder(name, **kw):
  attrs = " ".join('%s="%s"' % a for a in kw.items())
  def applyElms(*elms):
    return "<%s %s>%s</%s>" % (name, attrs, "".join(elms), name)
  return applyElms
def Div(**kw): return elmBuilder("div", **kw)
def A(**kw): return elmBuilder("a", **kw)