use-package & name conflict: why they are not deferred?

This is a discussion on use-package & name conflict: why they are not deferred? within the lisp forums in Programming Languages category; ïk, I see there is some delay until message occurs in a group. Sorry for duplicate messages. Behavior I desire can be achieved when use-package would do the following: i) if current package is a home package for one of conflicting symbols, this symbol is kept and other is not interned. ii) if both symbols are not of current package, they both are unimported. What this would lead to? I would have more "dirty" state of package system then "well bred" lispers. I'll be able to use all packages even if they have conflicts. I would use unqualified names for ...

Go Back   Application Development Forum > Programming Languages > lisp

Object Mix

Register FAQ Calendar Search Today's Posts Mark Forums Read
  #11  
Old 10-26-2008, 02:25 PM
budden
Guest
 
Default Re: use-package & name conflict: why they are not deferred?

ïk, I see there is some delay until message occurs in a group. Sorry
for duplicate messages.

Behavior I desire can be achieved when use-package would do the
following:
i) if current package is a home package for one of conflicting
symbols, this symbol is kept and other is not interned.
ii) if both symbols are not of current package, they both are
unimported.

What this would lead to? I would have more "dirty" state of package
system then "well bred" lispers. I'll be able to use all packages even
if they have conflicts. I would use unqualified names for non-
conflicting symbols and full names for conflicting ones. So, I would
be able to use any lisp code, but my code won't be usable by "well
bred" lispers.

Why do I think such possibility is important?

It is as I'd like to massively use a read-macro based construct
#with-package(designator-for-list-of-packages &body body)

Tim Bradshaw has something like this: http://www.tfeb.org/lisp/hax.html#READ-PACKAGES

This #with-package would read its body with packages temporarily used.
This way, I'll be able to make my program consising of hundreds and
even thousand packages. What does it mean?

In "modern" OO languages such as C++ or Java, each class in fact
introduces its own namespace. When you use a slot/method of a class in
a definition of other method, you are into that namespace, so you
don't need to fully qualify slots/members of that class. It is
reasonable as class might encapsulate many or most of the data
required for method definition. This leads to shorter, more easily
reading code. In Perl, class is distinctly bound to namespace. Pascal
has a with construct which joins namespaces from several records. SQL
implies namespace merging in its "select" statement. I think, this
approach is good. Surely my esthetic taste appeals me to get rid of
that ugly code like that:

(let ((foo (make-foo))
(print (foo-a foo) (foo-b foo)))

Human reader is clever enough to catch a "context". It is annoying to
read that repeating foo-. Look at human conversation. It is a good
style in a human communication not to repeat the same word too
frequently. And it is reasonable, as text with less repeating words
brings more information (in strict mathematical sence). If we really
need to repeat some words, it occurs that they are short (as "it",
"me", "let's", "and" etc). Context are used by human readers/writers
instead of repeating the same word again and again. Lisp violates both
that rules and I think it is mostly due to weakness of package system.

Compare code from swank:
(defstruct (arglist (:conc-name arglist.))
required-args ; list of the required arguments
optional-args ; list of the optional arguments
key-p ; whether &key appeared
keyword-args ; list of the keywords
rest ; name of the &rest or &body argument (if any)
body-p ; whether the rest argument is a &body
allow-other-keys-p ; whether &allow-other-keys appeared
aux-args ; list of &aux variables
known-junk ; &whole, &environment
unknown-junk) ; unparsed stuff

(defun encode-arglist (decoded-arglist)
(append (arglist.required-args decoded-arglist)
(when (arglist.optional-args decoded-arglist)
'(&optional))
(mapcar #'encode-optional-arg (arglist.optional-args decoded-
arglist))
(when (arglist.key-p decoded-arglist)
'(&key))
(mapcar #'encode-keyword-arg (arglist.keyword-args decoded-
arglist))
(when (arglist.allow-other-keys-p decoded-arglist)
'(&allow-other-keys))
(cond ((not (arglist.rest decoded-arglist))
'())
((arglist.body-p decoded-arglist)
`(&body ,(arglist.rest decoded-arglist)))
(t
`(&rest ,(arglist.rest decoded-arglist))))
(when (arglist.aux-args decoded-arglist)
`(&aux ,(arglist.aux-args decoded-arglist)))
(arglist.known-junk decoded-arglist)
(arglist.unknown-junk decoded-arglist)))

To hypothetical
(defpackage :arglist (:export :arglist :d-a))

#with-packages((:arglist)
(defstruct-exporting-slots (arglist (:conc-name ""))
required-args ; list of the required arguments
optional-args ; list of the optional arguments
key-p ; whether &key appeared
keyword-args ; list of the keywords
rest ; name of the &rest or &body argument (if
any)
body-p ; whether the rest argument is a &body
allow-other-keys-p ; whether &allow-other-keys appeared
aux-args ; list of &aux variables
known-junk ; &whole, &environment
unknown-junk) ; unparsed stuff

(defun encode-arglist (d-a) ; d-a is decoded-arglist
(append (required-args d-a)
(when (optional-args d-a)
'(&optional))
(mapcar #'encode-optional-arg (optional-args d-a))
(when (key-p d-a)
'(&key))
(mapcar #'encode-keyword-arg (keyword-args d-a))
(when (allow-other-keys-p d-a)
'(&allow-other-keys))
(cond ((not (rest d-a))
'())
((body-p d-a)
`(&body ,(rest d-a)))
(t
`(&rest ,(rest d-a))))
(when (aux-args d-a)
`(&aux ,(aux-args d-a)))
(known-junk d-a)
(unknown-junk d-a)))
)

Do you agree that the second code is much easier to read?

But if I try to combine this approach to CL standard "conflict free"
package system state, this becomes practically unusable due to symbol
clashes. I think lisp loses there in a competition to modern
languages.
Reply With Quote
  #12  
Old 10-26-2008, 03:26 PM
smallpond
Guest
 
Default Re: use-package & name conflict: why they are not deferred?

On Oct 25, 9:51 am, budden <budde...@mtu-net.ru> wrote:
> Hallo, group!
> I replied to the topic, but my message didn't appear. Don't know if
> it is a bug or moderation?
>
> > I'm not sure one can compare that.

>
> Each sql table defines a namespace where every its field presents as a
> symbol.
> Joining two tables is equavalent to (locally) using both namespaces at
> one time.
>
> > Not well-defined means you don't know where the error should occur. Are you

>
> sure what ``well-defined'' means?
> Sorry for my English. Maybe "poorly designed" is more correct.
>
> > Hmm, I would like to get the error as early as possible.

>
> (defpackage 1 (:exports :sym :sym1))
> (defpackage 2 (:exports :sym :sym2))
> (use-package 1)
> (use-package 2)
> (print 'sym1)
> ; end of file
>
> Does this program contain an error? Not in CL standard sence, in
> common sence.
>
> E.g. consider
>
> you: We'll be talking about walrus and oysters
> me: Package error: symbol 'eye' clashed
>
> vs
>
> you: We'll be talking about walrus and oysters
> me: ok
> you: first lets talk about a tusks
> me: (have read tusk as walrus:tusk) ok
> you: then about their eyes
> me: (read error: symbol 'eye' clashes)
>


error: symbol EYES is not defined in package OYSTER.
Reply With Quote
  #13  
Old 10-27-2008, 08:33 AM
Rainer Joswig
Guest
 
Default Re: use-package & name conflict: why they are not deferred?

In article
<88e8f641-3e14-4a33-b967-ad62b4d477f4@u75g2000hsf.googlegroups.com>,
budden <budden01@mtu-net.ru> wrote:

> ïk, I see there is some delay until message occurs in a group. Sorry
> for duplicate messages.
>
> Behavior I desire can be achieved when use-package would do the
> following:
> i) if current package is a home package for one of conflicting
> symbols, this symbol is kept and other is not interned.
> ii) if both symbols are not of current package, they both are
> unimported.
>
> What this would lead to? I would have more "dirty" state of package
> system then "well bred" lispers. I'll be able to use all packages even
> if they have conflicts. I would use unqualified names for non-
> conflicting symbols and full names for conflicting ones. So, I would
> be able to use any lisp code, but my code won't be usable by "well
> bred" lispers.


How do I know that there is a conflict? What thing would
tell me a development time that there is a conflict so that
I have to write foo:bar? Whether there is a conflict or
not depends on the packages and on the runtime state
of some Lisp program. Same problem, it just looks a bit differently.

> Why do I think such possibility is important?
>
> It is as I'd like to massively use a read-macro based construct
> #with-package(designator-for-list-of-packages &body body)
>
> Tim Bradshaw has something like this: http://www.tfeb.org/lisp/hax.html#READ-PACKAGES


That's some thing Lisp Machine Lisp had. It allows one to tell the default
package by expression.

> This #with-package would read its body with packages temporarily used.
> This way, I'll be able to make my program consising of hundreds and
> even thousand packages. What does it mean?
>
> In "modern" OO languages such as C++ or Java,


Well, C++ appeared in 1983 before the first Common Lisp book was
published (1984). C++ was based on developments from 1979
(C with classes). Java appeared in 1995 and was a very conservative
design, introducing not much new at the language level.
I don't think there is that much 'modern' to C++ and Java (the language).
Java now has a lot of stuff, but the designers are still thinking if closures
are worth to add and in what form. Go figure.

>each class in fact
> introduces its own namespace. When you use a slot/method of a class in
> a definition of other method, you are into that namespace, so you
> don't need to fully qualify slots/members of that class. It is
> reasonable as class might encapsulate many or most of the data
> required for method definition. This leads to shorter, more easily
> reading code. In Perl, class is distinctly bound to namespace. Pascal
> has a with construct which joins namespaces from several records. SQL
> implies namespace merging in its "select" statement. I think, this
> approach is good. Surely my esthetic taste appeals me to get rid of
> that ugly code like that:


Common Lisp tries not to mix all kinds of orthogonal business (classes,
namespaces, modules) into one base construct. If you look at the
base of Common Lisp, it goes exactly the other way. For example:
there are a few special forms - not many and a lot can be built on top.
This classes are modules are namespaces is not that popular in
the Lisp world. It is also a bit painful to use in interactive environments.
The Dylan language derived from Common Lisp and Scheme, also does
not go that route.


>
> (let ((foo (make-foo))
> (print (foo-a foo) (foo-b foo)))
>
> Human reader is clever enough to catch a "context".


The question is where that context comes from. If you are used
to non-interactive text-based environments, then you have
just one context: the text. In Lisp you work interactively
and additionally code is data - so the context can be quite different
and very non-obvious.

....

> (defun encode-arglist (decoded-arglist)
> (append (arglist.required-args decoded-arglist)
> (when (arglist.optional-args decoded-arglist)
> '(&optional))
> (mapcar #'encode-optional-arg (arglist.optional-args decoded-
> arglist))
> (when (arglist.key-p decoded-arglist)
> '(&key))
> (mapcar #'encode-keyword-arg (arglist.keyword-args decoded-
> arglist))
> (when (arglist.allow-other-keys-p decoded-arglist)
> '(&allow-other-keys))
> (cond ((not (arglist.rest decoded-arglist))
> '())
> ((arglist.body-p decoded-arglist)
> `(&body ,(arglist.rest decoded-arglist)))
> (t
> `(&rest ,(arglist.rest decoded-arglist))))
> (when (arglist.aux-args decoded-arglist)
> `(&aux ,(arglist.aux-args decoded-arglist)))
> (arglist.known-junk decoded-arglist)
> (arglist.unknown-junk decoded-arglist)))


See WITH-SLOTS and WITH-ACCESSORS in Common Lisp / CLOS. It helps
to keep things shorter in some situations.

An example of WITH-ACCESSORS from McCLIM:

(defun presentation-history-next (history ptype)
"Go to the next input (forward in time) in `history' that is a
presentation-subtype of `ptype', respective to the pointer in
`history'. Returns two values: the found object and its
presentation type, both of which will be NIL if no applicable
object can be found."
(with-accessors ((pointer presentation-history-pointer)
(array presentation-history-array)) history
;; If no navigation has been performed, we have no object to go
;; forwards to.
(if (or (null pointer) (>= (1+ pointer) (length array)))
(values nil nil)
(progn
(incf pointer)
(destructuring-bind (object . object-ptype)
(aref array pointer)
(if object-ptype
(if (presentation-subtypep object-ptype ptype)
(values object object-ptype)
(presentation-history-next history ptype))
(values nil nil)))))))

....

> (defun encode-arglist (d-a) ; d-a is decoded-arglist
> (append (required-args d-a)
> (when (optional-args d-a)
> '(&optional))
> (mapcar #'encode-optional-arg (optional-args d-a))
> (when (key-p d-a)
> '(&key))
> (mapcar #'encode-keyword-arg (keyword-args d-a))
> (when (allow-other-keys-p d-a)
> '(&allow-other-keys))
> (cond ((not (rest d-a))
> '())
> ((body-p d-a)
> `(&body ,(rest d-a)))
> (t
> `(&rest ,(rest d-a))))
> (when (aux-args d-a)
> `(&aux ,(aux-args d-a)))
> (known-junk d-a)
> (unknown-junk d-a)))
> )


Well, short notations are preferred by some (see Paul Graham's 'Arc language),
but not by me. I like code where the variable and function names are not
obfuscated. I'm not good in decrypting source code. Goethe could
have also abbreviated his works.

c=charlotte, w=werther, a=albert

One fine evening in winter, when the weather seemed inclined to
thaw, c and a were returning home together. The
former looked from time to time about her, as if she missed w's
company. A began to speak of him, and censured him for his
prejudices. He alluded to his unfortunate attachment, and wished
it were possible to discontinue his acquaintance. "I desire it on
our own account," he added; "and I request you will compel him to
alter his deportment toward you, and to visit you less frequently.
The world is censorious, and I know that here and there we are
spoken of." C made no reply, and A seemed to feel
her silence. At least, from that time he never again spoke of
W; and, when she introduced the subject, he allowed the
conversation to die away, or else he directed the discourse into
another channel.

There are opportunities for even more compression...

> Do you agree that the second code is much easier to read?


Not at all.

> But if I try to combine this approach to CL standard "conflict free"
> package system state, this becomes practically unusable due to symbol
> clashes. I think lisp loses there in a competition to modern
> languages.


Which of these 'modern languages' you think of is designed to be use
fully interactively and dynamic? Definitely not Java and not C++.

My advice:

* don't fight the language
* understand that Lisp is different (interactive, dynamic, introspective,
reflective, ...) and thus difficult to compare to static
language designed for batch use (C++, Java, ...)
* try to find out what the built-in way is to write shorter code
* write self-documenting code
* if you really want to write shorter code on a micro level
switch to another programming language
* if you want shorter code on a 'macro' level, stay with Lisp
* check out the style guide from Pitman/Norvig
http://lispm.dyndns.org/documents/Co...lisp-style.pdf

--
http://lispm.dyndns.org/
Reply With Quote
  #14  
Old 10-27-2008, 02:09 PM
Thomas A. Russ
Guest
 
Default Re: use-package & name conflict: why they are not deferred?

budden <budden01@mtu-net.ru> writes:

> Žïk, I see there is some delay until message occurs in a group. Sorry
> for duplicate messages.
>
> Behavior I desire can be achieved when use-package would do the
> following:
> i) if current package is a home package for one of conflicting
> symbols, this symbol is kept and other is not interned.
> ii) if both symbols are not of current package, they both are
> unimported.
>
> What this would lead to?


Chaos. Especially item "ii", since implementing that would have the
effect of unimporting a symbol that you might have already read.
Consider the following snippet:

(import kg1)

(.... sym ....)

(import kg2)

(.... sym ....)

Now, suddenly, SYM is no longer the same, because it has been
unimported, so when the reader gets to the second SYM, it has to create
a NEW symbol in the current package.

But it gets even worse, even if you do things all together in a
DEFPACKAGE form, rather than using the individual IMPORT statements:

(defpackage my-pkg (:use pkg1 pkg2))

(... sym ...)

Now, suppose that pkg1 exports SYM1 and pkg2 exports SYM2 and SYM.
There is no conflict, and the reader will happily use PKG2:SYM when it
encounters "sym". But what happens when the author of PKG1 decides to
extend it and now exports SYM as well. Suddenly, without warning from
the package system, the meaning of SYM in your code changes because
suddenly PKG2:SYM is no longer imported.

What you will find is that most of the time, when there is an attempt to
implement DWIM (Do What I Mean) behavior in programming languages, you
will get really strange behavior that is very difficult to debug.

--
Thomas A. Russ, USC/Information Sciences Institute
Reply With Quote
  #15  
Old 10-27-2008, 05:36 PM
Kaz Kylheku
Guest
 
Default Re: use-package & name conflict: why they are not deferred?

On 2008-10-26, budden <budden01@mtu-net.ru> wrote:
> In "modern" OO languages such as C++ or Java, each class in fact
> introduces its own namespace.


But these are not symbol namespaces but rather referential namespaces.

All symbols in C++ are in fact in one global namespace.

Given foo::x and bar::x, you are actually talking about three names: foo, bar
and x. The two x's are actually the same name.

So for instance if B is base class, D is derived, then D::x hides B::x.

There are more quirks in the design. Suppose that B::x is a virtual function
and D::x is also a function, and has the same type signature. D::x then
overrides B::x.

If a D object is accessed through a reference R to B, then R.x actually refers
to D::x. However, R.B::x refers to B::x.

> When you use a slot/method of a class in
> a definition of other method, you are into that namespace, so you
> don't need to fully qualify slots/members of that class.


Really? See above. If you're in the scope of class B, and call a function x,
you might actually be going to D::x, even though nothing is known about any D
in that scope. You have to use scope resolution to reach B::x.

Virtual functions can sneak up on you. Suppose a base class designer decides to
flip some regular function into being virtual. Oops; all functions in derived
classes which have the same name and a compatible signature are now overrides
of that function.

C++ has a pitifully stupid design with regard to how things are named, scoped
and referenced.

> It is
> reasonable as class might encapsulate many or most of the data
> required for method definition. This leads to shorter, more easily
> reading code. In Perl, class is distinctly bound to namespace. Pascal
> has a with construct which joins namespaces from several records.


It's not surprising you're a fan of Pascal's WITH.

Basically, you like brainadamaged things and you want Lisp to be that way.

Let's look at WITH:

(* in a procedure *)
VAR x : INTEGER;

WITH some_record ; BEGIN
y := func(x);
END

Above, func(x) refers to the local variable x, and y refers to some_record.y.

But suppose someone now maintains the program, and adds a field called x to
some_record. Oops! The stupid WITH statement now makes x refer to the x in the
record! The meaning of the assignment statement silently changes, and the
software breaks.

Think about how idiotic that is: a change done in some remote location of the
program, perhaps in another file, changes a meaning of a local variable
reference. Oops, I mean, what other file; Pascal originally didn't have
modules.

Modula-3 has a sanely designed WITH construct, which is similar to Lisp's
SYMBOL-MACROLET. It's something like:

WITH y = some_record.y, x = some_record.x[i] ; DO
...
END

See, you explicitly write every symbol that is introduced into the scope. There
are no hidden clashes.

Ada doesn't inherit Pascal's WITH statement either. Ada has a WITH statement
which does something else: it's used for bringing in packages.

Oberon has a WITH keyword, but the semantics is completely different something
like Lisp's TYPECASE.

So if we look at some of the predominant descendants of Pascal, we find that
the designers have not only repented the WITH mistake, but they sealed its fate
by reusing the word for other uses!

See, by redefining WITH, the language definitions of Ada, Modula 3 and Oberon
prevent implementors from providing a Pascal WITH as a backward-compatibility
extension for doing quick-and-dirty ports of questionable Pascal source.

Ada's WITH has the properties you like: you can use WITH to import packages
with clashing symbols. The clashes are identified as ambiguous at the point
where the symbols are used. This is perfectly fine in a language with a
well-defined compile time, in which all of the symbolic drama is played out to
its completion. If an Ada program builds with no ambiguous symbol references,
then there is no further worry.

> Human reader is clever enough to catch a "context".


That's great if you are writing programs to be executed by humans,
rather than machines.

> But if I try to combine this approach to CL standard "conflict free"
> package system state, this becomes practically unusable due to symbol
> clashes. I think lisp loses there in a competition to modern
> languages.


The question is, do we want to win in a race for the bottom?
Reply With Quote
  #16  
Old 10-28-2008, 10:14 AM
John Thingstad
Guest
 
Default Re: use-package & name conflict: why they are not deferred?

På Mon, 27 Oct 2008 22:36:31 +0100, skrev Kaz Kylheku <kkylheku@gmail.com>:

>
> All symbols in C++ are in fact in one global namespace.
>


Nop. All names are strings in the BSS segment. But each file can have it's
own. If you define a function to be static it is local to that file. Also
C++ offers a namespace construct which allows you to explicitly create
namespaces. (whic allows multiple files to share a namespace)

--------------
John Thingstad
Reply With Quote
  #17  
Old 10-29-2008, 06:11 AM
budden
Guest
 
Default Re: use-package & name conflict: why they are not deferred?

Hi group.
I see I was wrong in how I suggested to implement "liberate
namespace merging" concept. Really, idea of uninterning a symbol upon
using conflict is completely idiotic Let's fix it. What needs to be
changed is in-package.
Consider

(in-packages package &rest more-packages)
for file-level and
#with-packages((package &rest more-packages) &body body)

What does it mean?
All package namespaces are merged. You may use all external symbols
without package prefix unless it participates in a conflict. If there
are package clashes, they are reported not at in-package execution
time, but at read time. All new unqualified symbols are interned into
first package. If you refer to clashing symbol as package::symbol, no
conflict is reported. Optionally, clashes may be reported as a
warnings at the time (use-packages ) is processed.

Why this is better then modifying use-package? It is an extension of
cl, not a modification.
> It's not surprising you're a fan of Pascal's WITH.

No, I'm not. But if WITH were fixed, it might be much more useful.
Consider

unit p1;
var sym,sym1:integer;
type p2=record
sym,sym2:integer;
end;

function foo;
var use_p22;
var sym:integer;
begin
with use_p2 do
begin
sym1=sym2; { no ambiguity }
unit.sym; { refers to global var }
function.sym; { refers to local var }
use_p2.sym; { refers to use_p2 }
sym; { error: clashed }
end;
end;

They might fix it by adding a compiler switch which would allow either
strict namespace merging semantics (no ambiguities allowed) or
compatibility mode (as pascal does).

If it were so, I'd used with anywhere.

If you consider all the situation that can occur in programming
practice, you'll see that all is Ok there:

1. Starting learning new and yet unknown package. Just
write
(defpackage :test-package (:use))
(in-packages :test-package :my-favorite-libraries :new-package-to-
learn)
- all new symbols are interned to test-package.
- if no symbol clashes, all is ok; Use all symbols from my-favorite-
libraries and new-package-to learn without package prefix).
- if symbol clash appear, compiler reports a error exactly in the
place where it occured. You can just qualify your symbol and recompile
until no error occurs. Do not care this until this happens: compiler
want let you to err.
2. Adding new symbol to either package in a complex system
- no conflicts at export time (consider CL: your package is used
everywhere. To maintain correctness of use-package declration, cl
gives you a error when exporting a symbol with #'export creates a
symbol clash in some of the dependend packages. Things are worse when
your packages is used by someone else. He pulls an update from CVS and
occasionally gets a package error in a code he never even seen)
- all previously compiled code remains valid
- upon next recompilation all the places where symbol clash is
created, are reported. Recommended way of conflict resolution is to
qualify previously unqalified symbols. As project grows, more and more
symbols get prefixed with package names. It is reasonable.
3. Changing package context on the fly. Just see point 2.
4. What I've missed?

That is all for an essence of the question discussed. What goes to
lyrics/phylosophy,
> My advice:
>* don't fight the language
>* understand that Lisp is different (interactive, dynamic, introspective,

reflective, ...) and thus difficult to compare to static
language designed for batch use (C++, Java, ...)
I'm not fighting the language, I only finding a way to code
efficiently. Time=money. Efficiency=more free time. I'm neither
idealising nor debasing lisp. I'm totaly neutral. Lisp has many
wonderful and unique features, but I'm not going to disregard its
flaws.
I'm using lisp occasionally for nine years, so I think I at least
glanced at every CLHS entry. So thanks, no need to advice me to use
#'describe, #'documentation or with-slots.
What goes to dynamic nature, I not agree. Compilation in lisp has well
defined semantics and it is strict enough, so lisp _can_ act as a
compiled language, especially with the help of evel-when.

> I don't think human communication is a particular good

comparison. Common Lisp is not an 'artificial intelligence'
in itself.
Consider full software lifecycle. If it is not ideally documented,
developer would read code. Compare a time and cost of the following
parts of the large project life cycle:
1 human writes code
2 human reads code
3 computer reads code
4 computer writes code
5 human writes macros for internal DSLs
6 human writes code analysers for internal DSLs

I think in most sufficiently complex projects, item 2 will take most
of the time and cost (especially if code is self-documenting so no
documentation is created). So really efficient programming language
should be designed with human perception pecularities taken into
account. All consideration of style and other analogies to human
coversations are valid and relevant. If lisp failes to conform human
even simplest (and easy to conform) conventions of human conversation
style, it is a reason to change lisp.
Reply With Quote
  #18  
Old 10-29-2008, 06:21 AM
Rainer Joswig
Guest
 
Default Re: use-package & name conflict: why they are not deferred?

In article
<b8947092-40fb-4ee1-a80f-16a39a839e3d@m74g2000hsh.googlegroups.com>,
budden <budden01@mtu-net.ru> wrote:

....
> Consider full software lifecycle. If it is not ideally documented,
> developer would read code. Compare a time and cost of the following
> parts of the large project life cycle:
> 1 human writes code
> 2 human reads code
> 3 computer reads code
> 4 computer writes code
> 5 human writes macros for internal DSLs
> 6 human writes code analysers for internal DSLs
>
> I think in most sufficiently complex projects, item 2 will take most
> of the time and cost (especially if code is self-documenting so no
> documentation is created). So really efficient programming language
> should be designed with human perception pecularities taken into
> account. All consideration of style and other analogies to human
> coversations are valid and relevant.


I think reading and maintaining source code is sufficiently
different from other human activities (hunting, eating, having sex,
....) and needs highly trained people. Maintaining source
code is a recent activity in human evolution (50 years
of Lisp compared to 100000+ years of humans) , so one
would be very careful to see what capabilities humans
have acquired during evolution and what they have learned
during their education and what is actually helpful for this
particular task. By default the usually link to SICP
applies.

> If lisp failes to conform human
> even simplest (and easy to conform) conventions of human conversation
> style, it is a reason to change lisp.


Right, reading code is extremely important. Software maintenance
is the most costly thing in the whole life cycle of
software.

This favors having the context (the namespace) of the symbols visible
in the source and having a system that can be asked
about the various source artifacts (classes, functions,
declarations, documentation, ...). It enables humans to much
more easily get back into the context during maintenance.
It provides the extra information that is helpful. Abbreviating
symbols or not using namespace prefixes is actually decreasing
maintainability.

What you propose helps in quickly writing less maintainable
code. I guess that's fine for people who are paid
to get some result quickly and/or get paid for maintenance.

I favor using package prefixes in my sources.

For example to list the user objects of a web server in a CLIM window:

(define-a-http-ui-command (com-list-users info-command-table :menu t)
((realm 'http:realm))
(when realm
(clim:with-application-frame (frame)
(let ((*standard-output* (clim:frame-standard-output frame)))
(terpri)
(loop for user in (http:sorted-users realm)
do (climresent user))
(terpri)))))

I keep using the names for the CLIM and the HTTP package
to make clear where those symbols are coming from.

It gives me slightly more information than this version:

(define-a-http-ui-command (com-list-users info-command-table :menu t)
((realm 'realm))
(when realm
(with-application-frame (frame)
(let ((*standard-output* (frame-standard-output frame)))
(terpri)
(loop for user in (sorted-users realm)
do (present user))
(terpri)))))

And it saves me the effort of thinking about symbol clashes,
preparing a new packages using several packages
with possibly conflicting symbols and so on.

So it saves time during development (less clashes), debugging
(less clashes) and maintenance (improved readability).
Looks like a win to me.

--
http://lispm.dyndns.org/
Reply With Quote
  #19  
Old 10-29-2008, 12:44 PM
budden
Guest
 
Default Re: use-package & name conflict: why they are not deferred?

Ok, Rainer,

> This favors having the context (the namespace) of the symbols visible in the source and having a system that can be asked

about the various source artifacts (classes, functions, declarations,
documentation, ...).

I think it is more a matter of style. I earned most of my money up
to the date by supporting rather large SQL code. SQL namespace merging
policy is wise. I never had a problems with namespace clashes. So I'm
sure my proposed policy is fairly scalable.
What goes to lisp, my work is more like experiments and small
projects. You may or may not prefer prefixes to non-clashing symbols,
but I tired of getting problems with new packages. I just want to play
around with it and maybe I'll throw it away tomorrow. Say, I'm trying
package :foo. I remember very well that it is "foo" and I'm definitely
reluctant of writing `foo:' it everywhere. So for the first time I do
just "in-package :foo". But if several days pass, and package is Ok, I
want use my library too. And there symbol clashes interfere my work.
Lisp forces me to deal with symbol clashes when there is no real
conflict yet. It forces me to deside, which symbol is better:
"foo::common-word" or "my-lib::common-word". What if there are many
such symbols? All this it is not right. Solution I proposed solves
it.
But is usable not only in the short term, not in small projects. It
is safe. You'll never be able to enter ambigious symbols by occasion.
My SQL experience shows it is Ok.
If I'll learn Emacs or other developer's GUI to parse #with-
packages, my "find-source" feature will still be functional. This way,
it is no difference if I use prefixes or not. When returning to old
code, I can easily see what does the symbol means with that feature.
When I look for it two or three times, I'll remember it. So, no more
reading prefixes would be needed. Source would be shorter and I find
that convinient.
So, my solution is very good for the beginners and very acceptable
for maintainers.
I think now it is time to close the topic. If I'll stay on lisp, I
think I'll implement this feature for myself, make it available for
the public, and will actively use it.
Reply With Quote
  #20  
Old 10-30-2008, 11:10 AM
budden
Guest
 
Default Re: use-package & name conflict: why they are not deferred?

Good time of day Group...
I tried to implement what I wanted. Faced to difficulties that seem
to be impossible to solve:
1. No use of the feature without editor change. Not all editors are
available with sources.
2. Some low-level changes are required which go beyond flexibility
suggested by CL. E.g., I need to redefine intern and/or find-symbol.
But if they're inlined somewhere, it will fail.
Rainer, you were right when you adviced me not to fight the
language: language is stronger than me and I can't win and change it
to what I want. It is rather strange for a language whose main
advantage is its flexibility and extensibility...
So, maybe CL will be kept in my practice as a platform, but not as
an "end-user" language. Maybe I'll try to develop my own language with
lisp flaws fixed.

Reply With Quote
Reply


Thread Tools
Display Modes


All times are GMT -5. The time now is 11:55 PM.


Powered by vBulletin® Version 3.7.2
Copyright ©2000 - 2009, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.2.0
vB Ad Management by =RedTyger=

In an effort to better serve ads to our visitors, cookies are used on objectmix.com. For more information, check out our Privacy Policy.