Common Lisp The Language 2 outdated? - struct

In CLTL2 there is a struct example ice-cream-factory as follows, which would allegedly create two constructors. Here is the structure definition:
(defstruct (ice-cream-factory
(:constructor fabricate-factory
(&key (capacity 5)
location
(local-flavors
(case location
((hawaii) '(pineapple macadamia guava))
((massachusetts) '(lobster baked-bean))
((california) '(ginger lotus avocado
bean-sprout garlic))
((texas) '(jalapeno barbecue))))
(flavors (subseq (append local-flavors
'(vanilla
chocolate
strawberry
pistachio
maple-walnut
peppermint))
0 capacity)))))
(capacity 3)
(flavors '(vanilla chocolate strawberry mango)))
CLTL2 states:
The structure type ice-cream-factory has two constructors. The standard constructor, make-ice-cream-factory, takes two keyword arguments named :capacity and :flavors. For this constructor, the default for the capacity slot is 3 and the default list of flavors is America's favorite threesome and a dark horse (not a dead one).
However evaluating the standard constructor however runs into an undefined function error:
(make-ice-cream-factory)
The function COMMON-LISP-USER::MAKE-ICE-CREAM-FACTORY is
undefined.
Is this because the part of the book doesn't correspond to the latest standard on defstructs?
Specifying the :constructor option i am having only one constructor fabricate-factory.

There is only one constructor. If it mentions two, then that's an error.
For details on standard Common Lisp, look at the ANSI CL standard and derived documentation like the DEFSTRUCT entry in the HyperSpec:
defstruct creates the default-named keyword constructor function only if no explicit :constructor options are specified, or if the :constructor option is specified without a name argument.
Since
(defstruct (ice-cream-factory
(:constructor fabricate-factory
(&key (capacity 5)
location
(local-flavors
(case location
((hawaii) '(pineapple macadamia guava))
((massachusetts) '(lobster baked-bean))
((california) '(ginger lotus avocado
bean-sprout garlic))
((texas) '(jalapeno barbecue))))
(flavors (subseq (append local-flavors
'(vanilla
chocolate
strawberry
pistachio
maple-walnut
peppermint))
0 capacity)))))
(capacity 3)
(flavors '(vanilla chocolate strawberry mango)))
has a constructor named fabricate-factory, there will be no default name constructor created.

CLtL2 not only is hopelessly obsolete, it never really specified CL at all. CLtL specified a version of the language, while CLtL2 was just some snapshot of what was happening during the standardisation process. This was widely-understood at the time, but seems to have been partly forgotten since.
That being said the section you are referring to is not an example of the book being obsolete: it's just a mistake in the book. Section 19.6, 'By-Position Constructor Functions' of CLtL2 starts with this text:
If the :constructor option is given as (:constructor name <arglist>), then instead of making a keyword-driven constructor function, defstruct defines a "positional" constructor function, taking arguments whose meaning is determined by the argument's position rather than by a keyword.
(I've replaced italics by <angles> above.)
But then the example you are looking at just gets this wrong. Not only that it's internally-inconsistent: the text talks about a function make-ice-cream-factory but the example code contains make-factory.
A defstruct form which makes the code of the example be right would be
(defstruct (ice-cream-factory
(:constructor fabricate-factory
(&key (capacity 5)
location
(local-flavors
(case location
((hawaii) '(pineapple macadamia guava))
((massachusetts) '(lobster baked-bean))
((california) '(ginger lotus avocado
bean-sprout garlic))
((texas) '(jalapeno barbecue))))
(flavors (subseq (append local-flavors
'(vanilla
chocolate
strawberry
pistachio
maple-walnut
peppermint))
0 capacity))))
(:constructor make-factory))
(capacity 3)
(flavors '(vanilla chocolate strawberry mango)))
while one which makes the text be right would be
(defstruct (ice-cream-factory
(:constructor fabricate-factory
(&key (capacity 5)
location
(local-flavors
(case location
((hawaii) '(pineapple macadamia guava))
((massachusetts) '(lobster baked-bean))
((california) '(ginger lotus avocado
bean-sprout garlic))
((texas) '(jalapeno barbecue))))
(flavors (subseq (append local-flavors
'(vanilla
chocolate
strawberry
pistachio
maple-walnut
peppermint))
0 capacity))))
(:constructor))
(capacity 3)
(flavors '(vanilla chocolate strawberry mango)))
All of this works as specified in CltL2 in an an ANSI-conformant implementation.

Related

Looping to search string variables with local list

I am working with a very long list of commodity names (var1). I would like to extract information from this list by creating a second variable (var2) that is equal to 1 if var1 contains certain keywords.
I was using the following code:
g soy = strpos(productsproduced, "Soybeans, ") | strpos(productsproduced, "Soybean, ") | strpos(productsproduced, "soybeans, ")| strpos(productsproduced, "soybean, ") | productsproduced == "Soybeans"
The list is much longer, given that the data was not properly coded, and each name appears in many different ways (as the excerpt in the code sample shows).
I believe that it would be much easier to work with a list (easier to look through the list certainly, and see if I am missing anything, etc.)
Unfortunately, it has been a while since I have worked with loops, but I was thinking something of the sort:
local mylist Soybean soybean Soybeans soybeans Soybeans, soybeans,
forval i = mylist {
g soy = strpos(var1, "`i'")
}
This doesn't quite work, but I am not sure how to code it. One definite issue is that Stata would not know in this case whether I would like it to use the or operator (yes, I would) or the and operator.
The spirit is evident; the details need various fixes.
local mywords Soybean soybean Soybeans soybeans Soybeans, soybeans,
gen soy = 0
foreach w of local mywords {
replace soy = soy | strpos(var1, "`w'")
}
What's crucial is that you need replace inside the loop; otherwise the loop will fail second time round on a generate as the variable already exists.
In fact this example reduces to
gen soy = strpos(var1, "oybean") > 0
on the assumption that oybean wouldn't match anything not wanted.
Standardising to lower case is often helpful
local mywords soybean soybeans soybeans,
gen soy = 0
foreach w of local mywords {
replace soy = soy | strpos(lower(var1), "`w'")
}

How do I perform array operations on J classes?

I'm playing around with J's object-orientation facilities. Consider the following extremely contrived code:
coclass 'Object'
create =: 3 : 'state =: 0'
increment =: 3 : 'state =: state + y'
destroy =: codestroy
cocurrent 'base'
objects =: (0 conew 'Object') , (0 conew 'Object') , 0 conew 'Object'
Let's say I want to call the increment method on each of the objects in the objects array. How do I do this in a J-tastic kind of way? The only way I could come up with was an intermediate verb:
o_increment =: 4 : 0
for_o. y do.
increment__o x
end.
)
3 o_increment objects
This works but is not very convenient. Is there a better way?
Because object references are a part of J's morphology, rather than syntax, they're harder to manipulate at run-time than other data. That is, object references are baked into names, rather than specified as free parameters.
So, there's two ways invoke a method on an array of objects, and both require explicit code. The first way — rarely used except in unusual circumstances — is to generate and then execute strings representing the fully-qualified name, including a direct (explicit) locative.
3 apply&>~ 'increment_' ,L:0 objects ,&.> '_'
Much more common is to use an indirect reference in an explicit code block, using one of the pre-defined local variables as the locative. For example:
3 dyad def 'increment__y x'"0 objects
or, equivalently:
incrementObjs =: dyad define
increment__x y
)
objects incrementsObjs"0] 3
In fact, JSoftware made a major backwards-compatibility-breaking change to the language in version 6 specifically to make this pattern more convenient. Previously (i.e. prior to v6), you would have had to write something like:
incrementObjs =: dyad define
o =. x. NB. x and y used to be spelled x. and y.
increment__o y NB. but increment__x. would raise an error
)
In any case, note that this incrementsObjs"0 objects reformulation of your explicit for_o. objects do. loop is actually not specific to OOP at all; it's the standard automation of iteration provided by J's array-oriented nature.
Which leads me to the real answer to your question: J is fundamentally an array-oriented language, and its objects are usually coarser-grained than they are in more familiar languages like Java or C#.
In those languages, it's common to have a collection of objects; in J, it's more common to have an object of collections. That is, the objects in mainstream OOP languages are "small", in some sense. In J, objects are large, because all data in J is large (I don't mean this in the physical "big data", GB sense: I mean it in a conceptual, philosophical, ℕ sense).
Therefore the actual most common way to express your problem:
coclass 'Object'
create =: 3 : 'state =: 0'
increment =: 3 : 'state =: state + y'
destroy =: codestroy
cocurrent 'base'
objects =: 'Object' conew 0 0 0
Note that last line there objects =: 'Object' conew 0 0 0; the original was
objects =: (0 conew 'Object') , (0 conew 'Object') , 0 conew 'Object'.
That is: rather than an array of 3 objects, we created one object, with an array of 3 values.
Note also that that's the only line of code I changed. The "refactoring" to go from an object handling scalar values to one managing an array of any number of values took zero bytes of code-changes.
But what about incrementing all the objects? Before, you had to say:
3 dyad def 'increment__y x'"0 objects
Now, you only need say:
increment__objects 3
And that's why this is the standard approach to OOP in J 1.
1 Well, a cynic might say that J's fundamental array nature in some way obviates or even conflicts with the aims of OOP, and that the OO features available in J were bolted-on as an afterthought during the ascendence of OOP in the late 90s coughPerlcough, but I'm no cynic. At least not publicly.
OOP has its place in J, especially for organizing large components in a dynamic system; it's used applied differently than in language whose fundamental philosophy is OO, rather than AO.
inl_z_ =: (cocurrent#] ".#] [)"1 0
allows you to run code in 1 or a list of objects
'state =: >: state' inl objects
To disagree with Dan, J is actually fantastic at dealing with lists of objects with this function. You can obviously prefilter the list in objects prior to calling the code. Search for inlC (and inlA) in mailing list for more advanced uses of inl such as interacting with caller locale parameters.
To agree with Dan, making an object has to have a good reason compared to the alternative of having a list of the would-be properties (and then a table of all of the record instances). One good reason tends to be that there are resources to allocate and free

Haskell-style sections in Common Lisp

In Haskell, if I have a lambda that looks like the following
(\x -> doStuff x y)
where y is from the surrounding scope, I could section it and turn it into
(`doStuff` y)
which is shorter and more concise (and one of the things I love the most about Haskell).
Now, in Common Lisp I would write the equivalent code as
(lambda (x) (do-stuff x y))
And this is actually a very common thing for me to be writing, but I feel even that tiny bit of boilerplate bothers me somewhat, so I wonder if there is a way to get something like the Haskell-style sections in Common Lisp?
Unless you are more experienced, I would propose that you learn to write Lisp in Lisp, not how to write Haskell in Lisp. The latter is not a good idea. Haskell works very different.
Lisp does not do any 'currying' (or schönfinkeling ;-) ).
You can write it as:
CL-USER 5 > (defun curry (fn arg) (lambda (&rest args) (apply fn arg args)))
CURRY
CL-USER 6 > (mapcar (curry #'expt 2) '(2 3 4 5 6))
(4 8 16 32 64)
It costs a bit efficiency that way, though.
CL-USER 7 > (mapcar (lambda (base) (expt base 2)) '(2 3 4 5 6))
(4 8 16 32 64)
I personally prefer the latter, because I have a real readable name for the variable. This helps in a debugger, where I see then a backtrace. Tools like these are probably more important in Lisp, than in Haskell.
CL-USER 12 > (mapcar (lambda (base) (expt base 2)) '(2 3 "four" 5 6))
error. Let's look at the backtrace:
CL-USER 12 : 1 > :bb
...
Condition: In EXPT of ("four" 2) arguments should be of type NUMBER.
Call to SYSTEM::ARGS-TO-BINARY-ARITHMETIC-FN-NOT-OF-TYPE {offset 189}
SYSTEM::FN-NAME : EXPT
SYSTEM::ARG1 : "four"
SYSTEM::ARG2 : 2
TYPE {Closing} : NUMBER
Interpreted call to (SUBFUNCTION :ANONYMOUS SYSTEM::ANONYMOUS-LAMBDA):
BASE : "four"
Now I can see that the thing has a name. I was passing the string "four" to the function with a variable named base.
Interactive development with REPL and debugging tools is common. Best prepare the code to be useful for this development style. Common Lisp is not optimized to provide full program compilers with extensive type checking - like in Haskell.
One of the main problems of Lisp is that it can be very hard to find out what a piece of code really does. The default (strict functional programs with prefix syntax) is relatively easy to understand. But there are many possibilities to change the meaning of code in Lisp (macros, read macros, symbol macros, the Meta Object protocol, advising, ...).
First rule: if you are writing basic Lisp code, stick with the basic syntactic and semantic possibilities. Write defensively. Expect that someone else needs to understand the code. For that the code should be readable, easy to understand, use common idioms and it should be debuggable.
In Haskell many people with math background want to write code in a very compact way with a high level of abstraction. You can do that in Lisp, too. But for ordinary code I would not go that route and for larger pieces of code, Lisp often uses other mechanisms (code transformations via macros, ...).
You can develop arbitrary special syntax for such forms. There're multiple variants. I, for instance, use a Clojure-inspired sharp-backquote syntax. Using it, your form will look like this:
#`(do-stuff % y)
I don't think you can do it directly, but...
If you know that you always want to do something that is equivalent to (lambda (x) (fun x lexical)) and simply want a shorter way of expressing that, you could, in theory, use a macro.
I would, personally, advise against doing so, (lambda (x) (fun x lex)) doesn't take much typing and removes one layer of obscurity from your code. But if it is a pattern that is sufficiently common that it warrants special handling, something like the following might do:
(defmacro section (function lexical)
(let ((sym (gensym))
`(lambda (,sym) (,function ,sym ,lexical))))
That makes the Haskell section:
(`doStuff` y)
become the Common Lisp section:
(section dostuff y)
I don't, as such, find it more readable, at least in the short, but if it was something that I did see again and again, I would indeed consider (and have done, more for experimental purposes than anything else) a macro to make it quicker (I have a half-baked macro, somewhere, that allows you to do things like (_ func _2 lexical _1) -> *(lambda (a b) (func b lexical a)) and that is sometimes handy, but doesn't really improve readability).
There's a sharp backquote read macro in Let Over Lambda that could work for this case:
CL-USER>
(print
'#`,(+ a1 y))
(LAMBDA (A1) (+ A1 Y))
(LAMBDA (A1) (+ A1 Y))
CL-USER>
(let ((y 2))
(mapcar #`,(+ a1 y)
(list 1 2 3 4)))
(3 4 5 6)
CL-USER>
This approach is very similar to the technique mentioned by #Vsevolod Dyomkin. Hoyte's version does have a few extra features, like building a lambda with any number of arguments. On the other hand, it's a bit harder to parse, because it's being expressed at one level higher notation, where in order to eval a form you have to unquote the backquote (using ',' in this example).
Scheme has the cut macro (in SRFI-26), which allows you to specify holes in a procedure call with <>. For example:
(cut doStuff <> y) ;; same as (lambda (x) (doStuff x y))
(cut - 5 <> 6 <> 7) ;; same as (lambda (x y) (- 5 x 6 y 7))
You could probably define something similar in CL.
I also missed the ease of Haskell-style function currying and composition when in common lisp. As a result I wrote the following package which defines reader macros for concise curry and composition in lisp (it uses the alexandria functions).
http://eschulte.github.io/curry-compose-reader-macros/
With this package (mapcar (compose (curry #'* 2) (curry #'+ 1)) (list 1 2 3 4)) becomes (mapcar [{* 2} {+ 1}] (list 1 2 3 4)). I now use this in nearly all of my CL projects and find it greatly reduces code size and increases readability.
The alexandria package exports the symbols curry and rcurry.
So in your case you just do
(alexandria:rcurry function arg) e.g., (rcurry #'do-staff y).
Rcurry and curry return functions so you need to funcall the result as usual.

Update the whole structure

Suppose I have some function which returns a struct:
(struct layer (points lines areas))
(define (build-new-layer height)
...
(layer list-a list-b list-c))
I want to keep track of the last returned result something like:
(define top-side (build-new-layer 0)) ; store the first result
...
(set! top-side (build-new-layer 0.5)) ; throw away the first result and store the new one
However, for that particular code I get the error:
set!: assignment disallowed;
cannot modify a constant
constant: top-side
Please, tell me what would be the right way to do what I want
What language are you using? it seems it's a matter of configuration, because in principle what you're doing should work. Go to the "choose language" window (Ctrl+L in Windows), click on "show details" and see if one of the options of the language currently in use disallows redefinition of variables. Alternatively, try using a different language.
Depending on where exactly you're going to use the stored result (I can't tell from the code in the question), you could pass it around as function parameters, in such a way that using a global variable is no longer necessary. This might be a better idea, relying on global state and mutation (the set! operation) is discouraged in Scheme.
If you always want to keep around the last layer, then you might prefer setting the last-layer every time one is built. Like this.
(define last-layer #f)
(define build-new-layer
(let ((save-layer #f))
(lambda (height)
(let ((new-layer (layer list-a ...)))
(set! last-layer save-layer)
(set! save-layer new-layer)
new-layer))))
Note: if the real problem is the 'constant-ness' of last-layer then build yourself a little abstraction as:
(define-values (last-layer-get last-layer-set!)
(begin
(define last-layer-access
(let ((last-layer #f))
(lambda (type . layer)
(case type
((get) last-layer)
((set) (set! last-layer (car layer)))))))
(values (lambda () (last-layer-access 'get))
(lambda (layer) (last-layer-access 'set layer))))

Lisp: How to override default string representation for CLOS class?

In Common Lisp, how can I override the default string representation of a CLOS class so that calls to format or princ will print something intelligible, even when objects of that class are embedded within other types, such as lists or arrays?
For example, if I call (format t "~a~%" x) when x holds an instance of my solution class, I want it to print something like #<SOLUTION genes: #(1 2 3) scores: #(4 5) rank: 6> instead of #<SOLUTION {BB7CD31}>.
So far, all I have managed to figure out is writing custom functions to handle printing structures that I know will contain instances of this class, but this is tedious. Surely Lisp provides some way to get this functionality for free?
You should be looking at print-object and print-unreadable-object. Suppose you have a class named FOO like so:
(defclass foo ()
((name :accessor foo-name)))
And you want to print instances like this: #<FOO "xyz"> where "xyz" is the content of slot name. In this case, the following implementation of print-object would do what you want:
(defmethod print-object ((obj foo) out)
(print-unreadable-object (obj out :type t)
(format out "~s" (foo-name obj))))
Check out print-object.
If you also look 22.1.3.13 Printing Other Objects it suggests print-unreadable-object as a common format macro for such situations

Resources