| Register | FAQ | Calendar | Search | Today's Posts | Mark Forums Read |
|
#11
| |||
| |||
| ï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. |
|
#12
| |||
| |||
| 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. |
|
#13
| |||
| |||
| 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/ |
|
#14
| |||
| |||
| 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 |
|
#15
| |||
| |||
| 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? |
|
#16
| |||
| |||
| 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 |
|
#17
| |||
| |||
| 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 bechanged 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_p2 2;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. |
|
#18
| |||
| |||
| 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 (clim resent 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/ |
|
#19
| |||
| |||
| 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. |
|
#20
| |||
| |||
| 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. |
![]() |
| Thread Tools | |
| Display Modes | |
In an effort to better serve ads to our visitors, cookies are used on objectmix.com. For more information, check out our Privacy Policy.