Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: Zoo: zsh oriented object



On Mar 18,  5:34pm, Marc Chantreux wrote:
} 
} My dream came true: Zoo is born! Now, i'm really afraid about doing
} something that cannot be reliable, usable, maintenable, ... . That's
} why i would appreciate some feedbacks, ideas or advices.

This is an interesting approach.  I think I can point out a few
misconceptions and suggest some improvements.

} A. 3 benefits of autoload -Uk (comparing with source)
} 
} sourcing files is traditionnaly done with the source command. You
} have to figure out by yourself where is your library and the fact you
} already sourced it.

This isn't entirely true.  The "source" command searches $path, just
as autoloading searches $fpath.  I'm also not convinced that there's
any particular benefit to using autoload -k over -z; I suspect it's
all a matter of what you want the contents of the files to look like.

} * files have a leading upper, directories have lower, so I can have an
}   fpath with the files Ldif and ldif/Entry
}
} * functions begin with upper and i try to have only verbs.

I'd have done this the other way round.  Since you're creating a "use"
wrapper around "autoload", and that's creating things that are to be
treated as namespaces rather than as commands, the file names needn't
correspond directly to class names.  E.g.,

use () {
    local lib=$1
    shift
    autoload -Uk $lib/_class
    $lib/_class "$@"
}

Now the directory can be named "Ldap" and the actual implementation
can be in Ldap/_class.  You still write "use Ldap".  I'm not really
suggesting that this is the best choice, this is just an example of
how you don't need to match class names to function files.

} B. about Zoo
} 
} The zoo concept is very simple: zsh can execute arrays (if the first
} element of the array is executable). Examples:
}
} obj=( echo "i'm an object" )
} $obj

Why do it that way rather than, say, with an alias?

alias $id="zoo/_object ${(q)class} ${(q)self}"	# No "eval" necessary

I can think of one reason:  Using variables allows you to declare the
objects "local".  Unfortunately your implementation of "new" puts the
actual object data in an associative array in the global scope, so
many of the benefits of locals are lost anyway.

What's really wanted here are ksh "discipline functions" that are
called automatically when a variable is assigned/referenced/unset.
Then there'd be a real reason to use a variable whose disciplines
call the zoo library, because locals could delete themselves when
when they go out of scope.

} So the new function is defined like this
} 
}     eval "$id=( zoo/_object $class $self )"
}     export $id $self

It's currently meaningless to export an associative array in zsh.  It's
almost meaningless to export an ordinary array (cf. "typeset -T").  The
environment holds only strings, and zsh doesn't do anything clever with
converting those strings into arrays or functions except in the special
cases like PATH/path where an explicit relationship between a scalar
and an array has been established.  $( ... ) sees all the variables in
the parent scope not because they've been exported, but because it's a
simple fork() of the parent shell and thus has a copy of its memory.

Where export is useful is when you want to have the variables stay
visible even across an exec().  That's directly supported only for
simple strings.  So you don't need the "export" there.

} In fact zoo/_object() is a dispatcher that launches functions
} according to the class name.

An alternate approach would be to actually define new functions for
each instantiated object, and call them directly.  Then instead of
$srv .host (with a space, so .host is an argument), you can write
$srv.host (no space).  Methods could be functions named with some
other convention, e.g. "$srv-search".  (I'd rather use ":" than "-"
but a trailing ":" already has a meaning for parameter expansion.)

It might be tricky to make that idea work with fields that can be
created (that is, new field names invented, as with associative
array keys) on the fly.  Instead you'd have to declare them up front
in the class definition.  Which might not be a bad thing.

} new Ldap srv directory.example.com cn=admin 'giv3m3r00t'
} host $( $srv .host )

I don't like having to use $( ... ) so often.  It's an expensive way
to substitute a string.  It feels wrong that you had to make "Echo"
a primitive in order to implement field accessors.  However, it's too
late at night for me to come up with a better suggestion. :-}

A final thought:  There ought to be some interesting things you can
do with "zcompile" that you haven't done yet.



Messages sorted by: Reverse Date, Date, Thread, Author