24 Sep 2016
Berlin Lispers Meetup
Tuesday, September 27th, 2016
8 pm onwards
St Oberholz, Rosenthaler Straße 72, 10119 Berlin
U-Bahn Rosenthaler Platz
We will try to occupy a large table on the first floor, but in case you don't see us,
please contact Christian: 0157 87 05 16 14.
Please join for another evening of parentheses!
24 Sep 2016 8:56pm GMT
30 Aug 2016
With just about one hour and a half to spare we managed to submit our entry for Ludum Dare 36. Ludum Dare is a regularly occurring, fairly well-known game jam the idea of which is to create a game from scratch in 48 hours by yourself or 72 hours in a team. Given that, unlike last time we tried to participate we actually managed to finish making something that resembles a game, I think it's worth noting what my experience was as well as my general thoughts on game programming in Lisp.
On the first day, I actually still had a university exam to partake in, so I couldn't start in the morning right away and I didn't have much time at all to prepare anything. This in turn lead to several hours being squandered on the first day trying to get collision detection working and fixing other graphical bugs. Most of that time was spent looking through hundreds of completely useless tutorials and code samples on the web. In general I find the quality of material in the game and engine areas to be absolutely atrocious. Most of the things you can find are either too sweeping, badly written, or assume some ridiculous game framework that makes the code very hard to decipher even if it were applicable as a general, decoupled algorithm. I'm not sure why this field in particular is so bad, or if I'm just searching wrong. Either way, it seems that every time I stumble upon a problem in that domain I have to invest a lot of time in finding the right material- not a very productive experience as you might guess.
All difficulties aside, after the first day we had a running game that let you interact with objects and pick things up into an inventory and so forth. Pretty much all of the progress you see here is my doing. My partner-in-crime was busy working on a random map generator using perlin noise maps, which only got integrated later. Naturally, the reason why we could move on to working on actual game related features much sooner than on our previous attempt at a Ludum Dare is that our engine, Trial, has advanced a lot since then and is much more ready for use. But it is still not there yet by a long shot. Especially a general collision detection and resolution system is a vital aspect that we just did not have the time and energy to incorporate yet. Collision is one of those notorious game development aspects because there's so many ways in which to get it slightly wrong, not to mention that depending on your geometry it can get quite complex quite quickly, not only in terms of performance, but also in terms of the necessary algorithms involved. We've set up a trello board now that should allow us to more easily track ideas we have for Trial and keep things organised.
I'm also thinking of focusing future Ludum Dares on one particular core component of the engine. For example next time we could work on a general dialogue tree system and an adventure or visual novel would lend itself very well to that. Or we could start working on a more powerful animation system with something like a puzzle game, and so forth. Another thing we need to get into is sound and music design. Just before the jam I was heavily focused on getting sound support incorporated, but especially the mixer part was giving me a lot of unprecedented design issues that I could not satisfactorily resolve in the small amount of time I had available to myself with exams still going strong. I hope to return to that and finish it off soon though. That should lay the path to adding sound to our games. Unfortunately it won't actually help with teaching how to make effects and music. I expect that despite my 8 years of violin and 3 years of saxophone practise I won't actually have much of a clue at all on how to compose music. Either way, there always has to be a start somewhere to get onto the road.
By the end of the second day we had finally gotten in some good work on the game aspects, having shed pretty much all of the engine troubles. Random map generation worked, you could place items and interact, and there were even some, albeit flowery-looking, mice running around. Things were much more smooth-sailing now thanks to Common Lisp and Trial's incremental and dynamic development capabilities. We did uncover some more issues with the underlying engine system that proved rather "interesting". I'll have to investigate solutions over the coming days. Most prominently one problem is that of accessing important structures such as the scene when it isn't explicitly passed as a parameter. Currently depending on where you are you can reach this through a special variable or through the global window registry. Both approaches feel not so great and I'd like to see if I can come up with a cleaner solution. We also found some problems in other libraries in the ecosystem such as qtools and flare. It's really great to get some good use out of these libraries and get an opportunity to improve them.
And then the third day marched on. We got some pretty good last-minute features in, namely actually being able to pick up the mice, cook them, and eat them to fill your stomach. Things were getting pretty tight on time towards the end as we were rushing to fix problems in the map generation and gameplay mechanics. Fortunately enough I planned in a lot of buffer time (~6 hours) for the deployment of the game too, as that actually proved to be a lot more problematic than I had anticipated. Not even a single platform was able to deploy right away and it took me until 2 in the morning to figure everything out. One of the mechanisms that Qtools offers in order to tie in custom libraries into the automated deploy process was not coded right and never tested fully, so that bug only showed up now. On Windows we had some access violation problems that were probably caused by Trial's asset tracking system constructing Qt objects before dumping. Fortunately I had anticipated such a thing and with a simple
(push :trial-optimize-pool-watching *features*) before compilation that disabled itself and things worked smoothly from there.
On Linux the issues were much more curious. Running it from SLIME worked fine. Deploying worked fine. Launching the binary from my host worked fine. But as soon as I tried to launch it from my VM, it would complain about not finding
libsmokebase.so despite the file sitting right there next to the binary, the system using an absolute path to it that was correctly constructed, and other libraries before it being loaded the same way actually working. I'm still not sure why that exactly happened, but I finally remembered that qt-libs augments your
LD_LIBRARY_PATH in order to ensure that, should a library want to automatically load another for some dumb reason -despite the load order being already exactly and properly done in-code- it would still resolve to our own custom files first. However, since environment variables aren't saved when the binary is dumped, this did not carry over to when it was resumed, so I had to make sure that Qtools automatically corrects those on warm boot. And as if by magic, now everything did indeed work!
And so I sleep-deprivedly submitted our entry and went off to sleep. Today I then finally got to catch up with some other things that had started to pile up because I didn't have any time to spare at all over the weekend and now I'm here writing this entry. A riveting recount of a tale, to be sure.
Now I want to take some time to talk about my general impression on writing games -or applications in general- in Common Lisp. This is going to be rough and you might hate me for what I'll say. That's fine. Hatred is a good emotion if you can divert its energy into something productive. So put your passion to it and go ahead, brave reader.
I'll start with my biggest gripe: libraries. While there's plenty of libraries around in terms of numbers, some areas are just severely lacking, and a lot of things are missing. Sure, for games there's bindings to SDL, but if you don't want to use that you're already pretty much out of luck. There wasn't any library to handle gamepad input, monitor resolution managing, 3d model file loading, or complex audio mixing until I added them all recently and that's not accounting for all the features that I got "for free" by using Qt. There's still so much more missing. Font loading and rendering is one current example that's bothering me in specific. We're using Qt for that right now but it sucks. It sucks big time. I want something that works. Some times there is one or some libraries around, but they're not a candidate to me because they're just not usable.
Now, I think it's worth noting what it takes for a library to become usable to me, so let me explain. First and foremost, it must have a non-viral license that allows me to use it freely, and potentially commercially, without repercussion. I don't intend on selling my crap any time soon, but someone might want to that might want to use my software to do it. I cannot accept something that would restrict them from doing so. Second, it must work natively cross-platform on at the very least Linux, Windows, and OS X. If you cannot deploy your application to all of those platforms you can forget about it- it might be a nice toy for your personal use, but don't have any illusions that everyone is using Linux or that people would bother to switch operating systems just for your program. Third, it must be easy to deploy. This includes but is not limited to minimal C dependencies. Deploying C dependencies is a bloody nightmare and the version mismatches will ruin your life. Sometimes C dependencies are unavoidable, but anything that creates a gigantic dependency tree is practically impossible to deploy on Linux across distributions without requiring people to install and potentially compile packages on their own system, which is such a ludicrous suggestion that you should feel ashamed for even considering it. End-users will often not know, nor care about how to do that, and certainly won't go through the trouble of finding out just to use your thing. Finally, it should have a nice interface for me, the programmer. I don't want to use a library that is just a bare-bones CFFI wrapper, or merely some magic "run" function and nothing else. If it's something like that I can probably write it better myself and quicker at that than it would take me to figure out how to use that library.
Libraries aside, Common Lisp is not a magic bullet. Most of the problems are still the exact same as in any other environment. The algorithms are the same, the implementations are roughly the same, the problems are about equivalent. Sure, Lisp is different and it is really cool, but again, don't make yourself any illusions of grandeur about it. Being such a small community there's just all the more pressure on everyone to put as much into it as possible to bring it up to par with the rest of the world. Just because Lisp has many convenient features that ease coding a lot doesn't remedy the fact that it is dwarfed utterly in man-power. I know man-power isn't everything but pretending the effects of thousands upon thousands of people working on things all over the world just aren't there is just as insane as expecting your productivity to increase hundred-fold if you add a hundred people to a project. So please, stay open and accepting about the issues that Lisp still has as an ecosystem. The easiest way to start would be by making sure that libraries have adequate documentation.
If you're fine with Lisp staying small, then that's absolutely alright by me. After all, I'm fine with that too, and actually don't really care about it growing either. What I do care about is the idiocy of pretending that somehow Lisp's advantages can trump the size of other ecosystems. That is plain lunacy. No matter how high the convenience, writing any amount of code is going to take time.
I really like Lisp, I have probably around a hundred projects written in it by now and I have not touched any other language for personal projects in years. But I don't merely want to like Lisp, I want to be able to tell other people about it with a good conscience. I want to be able to tell them "yeah sure, you can do that no problemo!" without having to fall into the Turing tar pit. I want to be able to show them my projects and tell them "man, that was fun!", not "man, I had to write like twenty libraries to get here, and I'm now finally done after many weeks of hard work, but it was kinda fun I guess."
As mentioned in the other article linked above I really don't want to come off as pushy. I don't want to tell anyone what to do. You do what you like. This is merely me venting my frustration about some of the attitudes I've seen around the place, and some of the problems I seem to be constantly dealing with when working on my projects. I don't like being frustrated, and that's why I'm writing about it. But that's all there is to it; I definitely wouldn't expect this to change anyone's mind or force them to do anything different. It's just another voice in the wind.
So how about mentioning some good aspects? Well, they were already buried in the above, I'd say. Incremental development is awesome, especially for games where a lot of small tweaks and extensive, interactive testing are necessary. Lisp is a very pretty language and I like it a lot more than anything else I've ever worked with so far. It has the potential to be fantastic... but it isn't there yet.
Now I think I'll go back to thinking on how to get it just a sliver more in that direction. Ludum Dare gave me a lot to think about and there's exciting changes ahead. Who knows what'll be possible by the time the next Ludum Dare comes around.
By the way, in case you'd like to talk to us and discuss problems, potential features, and generally just chat around about all things code, consider yourself encouraged to hop on by our IRC channel
30 Aug 2016 10:53pm GMT
I'm publishing a progress report for month August with detailed timelog and brief description of undertakings performed each day. This file also contains report for the previous iteration sponsored by Professor Robert Strandh.
The most important achievement was securing funds for a few months of work with the
Bountysource crowdfunding campaign. We've created some bounties to attract new developers.
#clim channel on
Freenode is active and we seem to regain the user base what results in interesting discussions, knowledge sharing and increased awareness about the project among non-clim users.
We have also gained valuable feedback about user expectations regarding the further development and issues which are the most inconvenient for them. We've added a new section on the website https://common-lisp.net/project/mcclim/involve which addresses some common questions and doubts and we have created a wiki on GitHub (not very useful yet https://github.com/robert-strandh/McCLIM/wiki).
During this time we are constantly working on identifying and fixing issues, cleaning up the code base and thinking about potential improvements. Curious reader may consult the git repository log, IRC log and read the logbook.
As a side note, I've exceeded time meant for this iteration by four hours, but I'm treating it as my free time. Additionally people may have noticed that I did some works on CLX not specifically related to McCLIM - this development was done on my own time as well.
Also, to address a few questions regarding our agenda - our roadmap is listed here: https://common-lisp.net/project/mcclim/involve. That means among other things, that we are concentrated on finishing and polishing the CLX backend and we are currently not working on any other backends.
If you have any questions, doubts or suggestions - please contact me either with email (email@example.com) or on IRC (my nick is jackdaniel).
30 Aug 2016 1:00am GMT
27 Aug 2016
- assoc-utils - Utilities for manipulating association lists - Public Domain
- caveman2-widgets-bootstrap - An extension to caveman2-widgets which enables the simple usage of Twitter Bootstrap. - LLGPL
- cells - A Common Lisp implementation of the dataflow programming paradigm - LLGPL
- cl-mpg123 - Bindings to libmpg123, providing cross-platform, fast MPG1/2/3 decoding. - Artistic
- cl-neovim - Common Lisp client for Neovim - MIT
- cl-out123 - Bindings to libout123, providing cross-platform audio output. - Artistic
- cl-soil - A thin binding over libSOIL.so which allows easy loading of images - BSD 2 Clause
- cl-sxml - SXML parsing for Common Lisp - GNU General Public License
- clump - Library for operations on different kinds of trees - FreeBSD, see file LICENSE.text
- dirt - A front-end for cl-soil which loads images straight to cepl:c-arrays and cepl:textures - BSD 2 Clause
- ext-blog - A BLOG engine which supports custom theme - BSD
- for - An extensible iteration macro library. - Artistic
- git-file-history - Retrieve a file's commit history in Git. - MIT
- illogical-pathnames - Mostly filesystem-position-independent pathnames. - BSD 3-clause (See illogical-pathnames.lisp)
- maxpc - Max's Parser Combinators: a simple and pragmatic library for writing parsers and lexers based on combinatory parsing. - GNU Affero General Public License
- parse-front-matter - Parse front matter. - MIT
- path-string - A path utility library - MIT
- pseudonyms - Relative package nicknames through macros - FreeBSD (BSD 2-clause)
- quantile-estimator.cl - Common Lisp implementation of Graham Cormode and S. Muthukrishnan's Effective Computation of Biased Quantiles over Data Streams in ICDE'05 - MIT
- queen.lisp - Chess utilities for Common Lisp - MIT
- read-number - Definitions for reading numbers from an input stream. - Modified BSD License
- simple-gui - A declarative GUI definition tool for Common Lisp - BSD
- slack-client - Slack Real Time Messaging API Client - Apache-2.0
- trivial-rfc-1123 - minimal parsing of rfc-1123 date-time strings - MIT
- with-cached-reader-conditionals - Read whilst collection reader conditionals - BSD 2 Clause
Updated projects: 3bmd, 3d-vectors, agm, alexandria, binfix, burgled-batteries, caveman, caveman2-widgets, cepl, cepl.camera, cepl.devil, cepl.sdl2, cepl.skitter, ceramic, chirp, city-hash, cl-ana, cl-async, cl-azure, cl-conspack, cl-ecs, cl-fad, cl-gamepad, cl-grace, cl-influxdb, cl-jpeg, cl-libuv, cl-messagepack, cl-messagepack-rpc, cl-mpi, cl-mtgnet, cl-oclapi, cl-opengl, cl-openstack-client, cl-pack, cl-quickcheck, cl-redis, cl-rethinkdb, cl-scan, cl-sdl2, cl-smtp, cl-strings, cl-tokyo-cabinet, cl-unification, cl-yaclyaml, cl-yaml, clack, classimp, clml, clos-fixtures, closer-mop, clx, clx-truetype, coleslaw, collectors, corona,croatoan, dbus, dendrite, dexador, dissect, djula, eazy-gnuplot, esrap, exscribe, external-program, fare-memoization, fare-scripts, fiveam, flare, fn, gendl, geneva, glkit, glsl-spec, gsll, iterate, json-mop, kenzo,lack, lambda-fiddle, lisp-namespace, lispbuilder, lparallel, mcclim, mel-base, neo4cl, oclcl, opticl, osicat, prometheus.cl, prove, qlot, qt-libs, qtools, qtools-ui, quickapp, random-state, rcl, remote-js, restas, rtg-math, serapeum, sip-hash, skitter, spinneret, squirl, stumpwm, treedb, trivia, trivial-documentation, trivial-nntp, trivial-open-browser, trivial-ws, trivialib.type-unify, ubiquitous, ugly-tiny-infix-macro,utilities.print-items, utilities.print-tree, varjo, vgplot, vom, weblocks, weblocks-utils, woo, wu-sugar.
Removed projects: scalpl.
27 Aug 2016 2:16pm GMT
25 Aug 2016
Dinosaur and Lisp has a nice hack for automating the Chrome dinosaur game with Common Lisp and CLX.
25 Aug 2016 2:30pm GMT
17 Aug 2016
Shareablee engineers grapple with some of the hardest challenges in social media analytics and big data. We are involved in every aspect of the product development process from brainstorming to coding and deployment. Products that we create drive decision-making at some of the world's most influential brands such as NFL, ESPN, Facebook, HBO, Ebay, Subway and Samsung.
- Build features and modules that our customers fall in love with
- Work on high volume data collection, storage, and transformation
- Develop reusable code and libraries for future use
- Optimize various processes for maximum speed and scalability
- Develop and maintain data collectors and aggregators
- Collaborate with product managers and team leads to build the right thing
- Collaborate with directors and senior developers to build things the right way
- 2+ years of work experience as a software developer.
- A degree in computer science or a related field.
- Proficiency in one or more of the following:
- Clojure, and/or another functional language
- Python or a similar high-level general purpose language
- Experience with (or very strong interest to learn) the following frameworks and tools: Storm, Hadoop, Cassandra, PostgreSQL, Redis, RabbitMQ, Kafka, Django, Elasticsearch
- Basic understanding of distributed computing paradigms
- Experience with Amazon Web Services, Big Data processing and Map/Reduce
- Integration of multiple data sources and databases into one system
- Data migration, transformation, and scripting
- Implement automated testing platforms and unit tests
- Proficiency with code versioning tools such as Git
- The ability to map continuous learning to every aspect of your life
- Humble confidence
Please send resumes and cover letter to firstname.lastname@example.org
17 Aug 2016 7:33pm GMT
16 Aug 2016
We are delighted and overwhelmed by the support that many of you have shown for our effort to crowdfund the maintenance and continued development of McCLIM. Never in our wildest dreams had we imagined that we would reach our highest monthly goal of 2000 USD in only a few days.
In addition to our regular maintenance and programmed improvements, at this level of funding, we will be able to post so-called "bounties", i.e., specific sums of cash for solving specific problems. Once posted, they will be available at this URL:
Like we mentioned in our initial appeal for contributions, this campaign has an important side-effect, beyond that of providing a budget for improvements, namely that of creating new excitement around McCLIM. This excitement will ultimately result in contributions in the form of code, thereby multiplying the importance of the direct monetary support.
In order to make our work on this project as transparent as possible, we will do our utmost to provide monthly reports on our progress, and we will provide details on how the cash was put to work.
We sincerely hope to make sufficient progress, sufficiently fast, that you will consider additional contributions, in the form of cash or code, in the future.
Robert Strandh and Daniel Kochmański
16 Aug 2016 1:00am GMT
12 Aug 2016
McCLIM is currently the only free native toolkit for developing GUI applications in Common Lisp. A while ago, I took over the maintenance, because I did not want to see McCLIM abandoned.
But since I have many other projects going, I decided to hire Daniel Kochmański part time (25%) to do some of the urgent work. This experience turned out so well that I would like for him to continue this work. Not only am I very pleased with the quality of Daniel's work, but I was also very surprised about the additional excitement that his work generated.
While I could continue funding Daniel myself for a while, I can not do so indefinitely. For that reason, I decided that we should try crowdfunding. Steady funding at the 25% level for a year or more would allow us to address some of the issues that often come up, such as the numerous remaining defects, the lack of modern visual appearance, and more.
If you are interested in seeing this happen, I strongly urge you to consider contributing to this project. Our target is modest. We would like to obtain at least 600 USD per month for at least one year. Even a small monthly contribution from a significant number of people can make this happen.
To contribute, please visit https://salt.bountysource.com/teams/mcclim and follow the instructions.
12 Aug 2016 1:00am GMT
11 Aug 2016
Setting up the basic environment
We assume that you already have configured the Common Lisp environment (including Quicklisp) and that you know the basics of the Common Lisp programming. The necessary systems to load are
clim-listener, you may load them with the Quicklisp. After that launch the listener in a separate thread:
(ql:quickload '(mcclim clim-listener)) (clim-listener:run-listener :new-process t)
Finding your way around CLIM
CLIM is the global minimum in graphics toolkits. Geometry, and means of abstracting it. Switch the listener into the CLIM-INTERNALS package to get started. Type
(in-package climi) in the
Evaluate the 4 following forms in
Slime REPL, then call
(cos-animation) in the
Listener REPL to demonstrate CLIM's animation capabilities. You cannot evaluate (cos-animation) in the
Slime REPL, as
*standard-output* is bound to the its output stream which isn't a
sheet, and thus cannot be drawn on.
(in-package climi) (defparameter *scale-multiplier* 150 "try modifying me while running!") (defparameter *sleep-time* 0.0001 "modify and eval to speed or slow the animation, set to `nil' to stop") (defun cos-animation () (let* ((range (loop for k from 0 to (* 2 pi) by 0.1 collect k)) ; length of 62 (idx 0) (record (updating-output (*standard-output*) (loop for x from (nth idx range) to (+ (nth idx range) (* 2 pi)) by 0.01 with y-offset = 150 for x-offset = (- 10 (* *scale-multiplier* (nth idx range))) for y-value = (+ y-offset (* *scale-multiplier* (cos x))) for x-value = (+ x-offset (* *scale-multiplier* x)) do (draw-point* *standard-output* x-value y-value :ink +green+ :line-thickness 3))))) (loop while *sleep-time* do (progn (sleep *sleep-time*) (if (= 61 idx) (setq idx 0) (incf idx)) (redisplay record *standard-output*)))))
If you want to stop the animation, issue in the
(setf *sleep-time* nil)
If it wasn't already obvious, you can plot w/e.
(CLIM-LISTENER::DRAW-FUNCTION-FILLED-GRAPH #'tanh :min-x (- 0 pi pi) :max-x pi :min-y -1.1 :max-y 1.5 :ink +blue+)
Drawning class hierarchy
,clear output history in the
Listener REPL and RET to clear the screen.
"," indicates that you are activating a command. Try typing comma, then C-/ to activate completion. C-c C-c to dismiss.
Children of the class
CLIMI::SHEET can be drawn on using arbitrary geometry. Try
(clim-listener::com-show-class-subclasses 'sheet) in the
Listener REPL to view the subclasses of it.
Commands and presentations
The name COM-whatever indicates that the function in question is a clim command, which you can define in the
Slime REPL like so,
(in-package clim-listener) ;;; Runme! We will need these in a moment. (dolist (image-name '("mp-avatar.png" "vulpes-avatar.png" "stas-avatar.png" "suit-avatar.png" "rainbow-dash-avatar.png" "chaos-lord-avatar.png")) (uiop:run-program (format nil "curl https://common-lisp.net/project/mcclim/static/media/tutorial-1/~A --output /tmp/~A" image-name image-name))) (define-listener-command (com-ls :name t) ((path 'string)) (clim-listener::com-show-directory path))
,ls /tmp/ -- then
,display image <SPACE> and click on one of the displayed paths to supply it as an argument. At the core of CLIM is the notion of a presentation. Objects have presentation methods, ie, some arbitrary rendering geometry, and when PRESENT'd on the screen CLIM remembers the type. Thus one can supply objects of the appropriate types as arguments to a command simply by clicking on them. Read about
CLIMI::DEFINE-COMMAND in the specification to learn more. Let's define our first presentation method.
Intermixing S-expressions with the presentation types
Evaluate the forms below in the
(in-package climi) (defvar lords '("mircea_popescu" "asciilifeform" "ben_vulpes")) (defclass wot-identity () ((name :accessor name :initarg :name :initform nil) (avatar :accessor avatar :initarg :avatar :initform nil))) (defmethod lord? ((i wot-identity)) (member (name i) lords :test #'string=)) (define-presentation-type wot-identity ()) (defun make-identity (name avatar-pathname) (make-instance 'wot-identity :name name :avatar avatar-pathname)) (defparameter *identities* (mapcar (lambda (l) (apply #'make-identity l)) '(("mircea_popescu" #P"/tmp/mp-avatar.png") ("ben_vulpes" #P"/tmp/vulpes-avatar.png") ("asciilifeform" #P"/tmp/stas-avatar.png") ("Suit" #P"/tmp/suit-avatar.png") ("RainbowDash" #P"/tmp/rainbow-dash-avatar.png") ("ChaosLord" #P"/tmp/chaos-lord-avatar.png")))) (define-presentation-method present (object (type wot-identity) stream (view textual-view) &key acceptably) (declare (ignorable acceptably)) (multiple-value-bind (x y) (stream-cursor-position stream) (with-slots (name avatar) object (draw-pattern* stream (climi::make-pattern-from-bitmap-file avatar :format :png) (+ 150 x) (+ 30 y)) (draw-text* stream name (+ 153 x) (+ 167 y) :ink +black+ :text-size 20) (draw-text* stream name (+ 152 x) (+ 166 y) :ink (if (lord? object) +gold+ +blue+) :text-size 20)) (setf (stream-cursor-position stream) (values x (+ 200 y))) object)) (defun eval-and-then-call-me-in-the-listener () (let* ((n 8) (sheet *standard-output*)) (labels ((gen (i) (let* ((out-and-start '(f x))) (loop for k from 0 to i do (setq out-and-start (apply #'append (mapcar (lambda (s) (case s ;; (x '(y f + f f + + x)) ;; (y '(y f + f f x - - f f x)) (x '(+ y f + f f + y y +)) (y '(f - y f f x f f)) )) out-and-start)))) (remove-if (lambda (sym) (member sym '(x y) :test 'eq)) out-and-start)))) (let* ((x 300) (y 300) (new-x x) (new-y y) (a 1) (step 15)) (loop for r in (gen n) do (progn (cond ((= a 1) (setq new-y (+ step y))) ((= a 2) (setq new-x (- x step))) ((= a 3) (setq new-y (- y step))) ((= a 4) (setq new-x (+ step x)))) (case r (f (clim:draw-line* sheet x y new-x new-y :ink clim:+blue+ :line-thickness 6 :line-cap-shape :round) (setq x new-x y new-y)) (- (setq a (if (= 1 a) 4 (1- a)))) (+ (setq a (if (= 4 a) 1 (1+ a)))) (t nil))))) (let* ((x 300) (y 300) (new-x x) (new-y y) (a 1) (step 15)) (loop for r in (gen n) do (progn (cond ((= a 1) (setq new-y (+ step y))) ((= a 2) (setq new-x (- x step))) ((= a 3) (setq new-y (- y step))) ((= a 4) (setq new-x (+ step x)))) (case r (f (clim:draw-line* sheet x y new-x new-y :ink clim:+white+ :line-thickness 2 :line-cap-shape :round) (setq x new-x y new-y)) (- (setq a (if (= 1 a) 4 (1- a)))) (+ (setq a (if (= 4 a) 1 (1+ a)))) (t nil))))))))
(dolist (i *identities*) (present i)) at the CLIM Listener.
(lord? at the listener and then clicking on one of the identities. Add a closing paren and RET. Notice how objects can be seamlessly intermixed with S-expressions. If this example fails for you it may be that you have not recent enough version of McCLIM.
Unripe fruits. The future isn't what it used to be - some assembly required.
(CLIM-DEMO::DEMODEMO)(available with system
The essential machinery of a 'live' GUI builder
Navigator (essentially an extended `apropos')
11 Aug 2016 1:00am GMT
19 Jul 2016
Thanks to Masayuki Takagi, a not-so-obvious bug was fixed in the basic unification machinery of CL-UNIFICATION. This led to the addition of a couple of new utility functions and some other cleanups (hopefully).
19 Jul 2016 10:58am GMT