One line paraphrase Lisp is nice and we used it and here's all the stuff that was broken with SBCL I had to fix.
We use SBCL for production deployment and CCL on most of the developers' machines. One of the nice things about Lisp is that you have an option of choosing from several mature implementations with different strengths and weaknesses: in our case, we optimized for processing speed on the server, and compilation speed in the dev environment
Quicklisp repository hosts more than 1,000 Lisp libraries — not a mind-blowing number but quite enough for covering all of our production needs.
Overall, the problems we face with integrating a Lisp app into the cloud world are not radically different from the ones we encounter with many other technologies. If you want to use Lisp in production, and to experience the joy of writing Lisp code, there is no valid technical reason not to!
oh noes!
We've built an esoteric application (even by Lisp standards), and in the process have hit some limits of our platform. One unexpected thing was heap exhaustion during compilation. We rely heavily on macros, and some of the largest ones expand into thousands of lines of low-level code. It turned out that SBCL compiler implements a lot of optimizations that allow us to enjoy quite fast generated code, but some of which require exponential time and memory resources.
We had to tune the generation sizes, and it turned out that the best option was to use an over-sized heap: our application consumes 2-4 gigabytes of memory, but we run it with 25G heap size which automatically results in a huge volume for the nursery. Yet another customization we had to make — a much less obvious one — was to run full GC programmatically every N minutes. With a large heap, we have noticed a gradual memory usage buildup over periods of tens of minutes which resulted in spans of more time spent in GC and decreased application throughput. Our periodic GC approach got the system into a much more stable state with almost constant memory usage.
oh noes!
Of all these challanges, the worst bug I've ever seen was a network bug. As usual with such stories, it was not a bug in the application but a problem in the underlying platform (this time — SBCL).
oh noes!
As we were just beginning running our service under substantial load in production, after some period of normal operation all of the servers would suddenly start to slow down and then would become unresponsive. After much investigation centering on our input data, we discovered that the problem was instead a race condition in low-level SBCL network code, specifically in the way the socket function getprotobyname, which is non-reentrant, was called.
This is useful
With trace, you define a function to trace, run the code, and Lisp prints all calls to that functions with arguments and all of its returns with results. It is somewhat similar to stacktrace, but you don't get to see the whole stack and you dynamically get a stream of traces, not stopping the application. trace is like print on steroids that allows you to quickly get into the inner workings of arbitrary complex code and monitor complicated flows. The only shortcoming is that you can't trace macros.
Name:
Anonymous2015-06-30 6:02
I've sent them my resume, but got no response
If you know somebody there, can you please recommend me and point to my repo (https://github.com/saniv)
Although I dunno if moving to Ukraine would really be possible during war.
>>9 In fact I love watching the chechclear video, where blonde soviet racist occupant is getting beheaded for his crimes against the chechen people. I'm all pro-exterminating the blue eyed blondes. Totally not racist minority rights activist.
Name:
Anonymous2015-07-01 7:00
>>7 What? I not familiar with Clojure. Only SBCL and Racket.
SHOULD This word, or the adjective "RECOMMENDED", means that there may exist valid reasons in particular circumstances to ignore the demands of the guideline, but the full implications must be understood and carefully weighed before choosing a different course. You must ask forgiveness for violating a SHOULD.
There are cases where transgression of some of these rules is useful or even necessary. In some cases, you must seek permission or obtain forgiveness from the proper people.
Conventional guidelines are indoctrination. Their purpose is to make you follow the mores of the community, so you can more effectively cooperate with existing members.
Often, the smallest hammer is to use an existing library. Or one that doesn't exist yet. In such cases, you are encouraged to use or develop such a library, but you must take appropriate precautions
You MUST NOT start a new library unless you established that none is already available that can be fixed or completed into becoming what you need. That's a rule against the NIH syndrome ("Not Invented Here"), which is particularly strong amongst Lisp hackers.
Use your judgment to distinguish general-purpose versus business-specific code, and open-source the general-purpose parts, while keeping the business-specific parts a trade secret.
Open-Sourcing code has many advantages, including being able to leverage third parties for development, letting the development of features be user-directed, and keeping you honest with respect to code quality.
Whatever code you write, you will have to maintain anyway, and make sure its quality is high enough to sustain use in production.
There should therefore be no additional burden to Open-Sourcing, even of code that (at least initially) is not directly usable by third parties.
Name:
Anonymous2015-07-01 12:41
I still have no idea how one gets a Lisp programming job.
All places I have sent my resume to I got no response from.
<!-- Common Lisp does not have global lexical variables, --> <!-- so a naming convention is used to ensure that globals, --> <!-- which are dynamically bound, --> <!-- never have names that overlap with local variables. --> Common Lispは大域レキシカル変数を持ちません、 命名についての慣習は大域変数の動的束縛と ローカル変数による名前の上書きからの保護を行います。 <!-- It is possible to fake global lexical variables --> <!-- with a differently named global variable --> <!-- and a <code>DEFINE-SYMBOL-MACRO</code>. --> これは違う名前の大域変数と<code>DEFINE-SYMBOL-MACRO</code>による 偽りの大域レキシカル変数によって可能になります。 <!-- You should not use this trick, --> <!-- unless you first publish a library that abstracts it away. --> あなたが最初にそれを抽象化するライブラリを発行する場合を除いて、 あなたはこのようなトリックを使うべきではありません。 </p>
<p> <!-- You should name boolean-valued functions and variables with a --> <!-- trailing <code>"P"</code> or <code>"-P"</code>, --> <!-- to indicate they are predicates. --> <!-- Generally, you should use --> <!-- <code>"P"</code> when the rest of the function name is one word --> <!-- and <code>"-P"</code> when it is more than one word. --> ブール値を返す関数や変数はそれらが述語であることを示すために<code>"P"</code>か<code>"-P"</code>で終わる名前とすべきです。 一般的に名前が単語の場合は、<code>"P"</code>を使い、複数語の場合は、<code>"-P"</code>を使うべきです。 </p> <p> <!-- A rationale for this convention is given in --> <!-- <a href="http://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node69.html">the CLtL2 chapter on predicates</a>. --> この慣習の根拠となるものには、 <a href="http://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node69.html">CLtL2 predicatesの章</a> があります。 </p>
<p> <!-- Your package must not shadow (and thus effectively redefine) --> <!-- symbols that are part of the Common Lisp language. --> パッケージでCommon Lispの仕様の一部となっているシンボルをシャドウ(そして事実上再定義も)してはいけません。 <!-- There are certain exceptions, --> <!-- but they should be very well-justified and extremely rare: --> 例外もありますが、これらはかなり正当化されているべきで、ほとんど起こらないはずです: </p> <ul> <li> <!-- If you are explicitly replacing a Common Lisp symbol --> <!-- by a safer or more featureful version. --> より安全、もしくはより多機能になるように明示的にCommon Lispのシンボルを再定義している場合。 </li> <li> <!-- If you are defining a package not meant to be "used", --> <!-- and have a good reason to export a symbol --> <!-- that clashes with Common Lisp, --> <!-- such as <code>log:error</code> and <code>log:warn</code> --> <!-- and so on. --> "use"されることを意図していなくて、Common Lispのシンボルと衝突してまでエクスポートするだけの理由があるパッケージを定義する場合。 例えば<code>log:error</code>や<code>log:warn</code>など。 </li> </ul>
<p> <!-- Lisp is best used as a "mostly functional" language. --> Lispは"極力関数型"言語としての使うのが最適です。 </p> <p> <!-- Avoid modifying local variables, try rebinding instead. --> 変数は変更(代入)するのではなく、再束縛を試みましょう。 </p> <p> <!-- Avoid creating objects and the SETFing their slots. --> <!-- It's better to set the slots during initialization. --> オブジェクトを生成してスロットに値をSETFするのではなく、 初期化時にスロットに値を設定する方がより好ましいでしょう。 </p> <p> <!-- Make classes as immutable as possible, that is, avoid giving slots --> <!-- setter functions if at all possible. --> 極力クラスは変更不可なものとして設計しましょう。換言すれば、それが可能な場合には、スロットにはセッター関数を付加しないということです。 </p> <p> <!-- Using a mostly functional style makes it much easier --> <!-- to write concurrent code that is thread-safe. --> <!-- It also makes it easier to test the code. --> 極力関数的スタイルに則せば、スレッドセーフな並行動作のコードを書くこともより易くなり、コードをテストするのもまたより易しくなります。 </p>
<p> <!-- Common Lisp systems are not required to implement --> <!-- function calls from tail positions without leaking stack space --> <!-- — which is known as proper tail calls (PTC), --> <!-- tail call elimination (TCE), --> <!-- or tail call optimization (TCO). --> Common Lispシステムは、真正な末尾呼び出し(PTC)や末尾呼び出しの削除(TCE)、および末尾呼び出し最適化(TCO)などとして知られる、 スタック空間の溢れることがない末尾位置での関数呼び出しの実装が要求されていません。 <!-- This means that indefinite recursion through tail calls --> <!-- may quickly blow out the stack, --> <!-- which hampers functional programming. --> これが意味するところは、末尾再帰での無限再帰であったとしてもスタックが即座に溢れてしまうかもしれず、これが関数的なプログラミングの妨げになる、ということです。 <!-- Still, most serious implementations (including SBCL and CCL) --> <!-- do implement proper tail calls, but with restrictions: --> とはいうものの、制約付きでもっとも実用的な実装(SBCLやCCL)は最適末尾呼び出しを実装しています: </p> <ul> <li> <!-- The <code>(DECLARE (OPTIMIZE ...))</code> settings --> <!-- must favor <code>SPEED</code> enough and --> <!-- not favor <code>DEBUG</code> too much, --> <!-- for some compiler-dependent meanings of "enough" and "too much". --> <code>(DECLARE (OPTIMIZE ...))</code>設定は、 いくつかのコンパイラにおける「十分」と「過度」の意味のために、 <code>SPEED</code>を十分に優先して、必要以上に<code>DEBUG</code>を優先しないように しなければなりません <!-- (For instance, in SBCL, you should avoid <code>(SPEED 0)</code> --> <!-- and <code>(DEBUG 3)</code> to achieve proper tail calls.) --> (例えばSBCLにおいて、あなたは末尾呼び出しの優先を結果として得るためには、 <code>(SPEED 0)</code>と<code>(DEBUG 3)</code>を回避すべきです)。 </li> <li> <!-- There should not be dynamic bindings around the call --> <!-- (even though some Scheme compilers are able to properly treat --> <!-- such dynamic bindings, called parameters in Scheme parlance). --> 関数呼び出しを包むような動的な束縛は避けるべきです。(訳注: 再帰的な関数呼び出しに伴ない、動的束縛が入れ子になると動的束縛も関数呼び出しとは別にスタックを消費するた>め、これが原因でスタックが溢れる) <!-- 動的束縛が再帰呼び出しで入れ子になり、結果としてスタックを溢れさせるのを避けるという意味だと思われますが原文が曖昧で良く分かりません -g000001 --> (いくつかのSchemeコンパイラはこのような、Schemeの用法でパラメタと呼ばれる動的束縛を適切に修正することができますが) </li> </ul>
<p> <!-- For compatibility with all compilers and optimization settings, --> <!-- and to avoid stack overflow when debugging, --> <!-- you should prefer iteration or the built in mapping functions --> <!-- to relying on proper tail calls. --> すべてのコンパイラと最適化設定、そしてデバッグ時のスタックオーバフローを回避するために、 組み込みの末尾再帰の最適化に依存するよりも、繰り返し構文、もしくはマッピング関数の利用をあなたは優先すべきです。 </p> <p> <!-- If you do rely on proper tail calls, --> <!-- you must prominently document the fact, --> <!-- and take appropriate measures to ensure an appropriate compiler is used --> <!-- with appropriate optimization settings. --> もしあなたが最適末尾呼び出しに依存することをするのなら、 あなたは、その動作の実際について明確に文書化し、適切な最適化設定と共に適切なコンパイラを使用することを保証するために 適切な措置を講じなければなりません。 <!-- For fully portable code, you may have to use trampolines instead. --> 完全な移植性をもつコード(訳注: 挙動がコンパイラのセッティングに依らないコード)のためには、あなたは代わりにトランポリンを使わなければならないかもしれません。 </p>
<!-- Do not clean up by resignaling. --> 再通知によって処理の後始末をしてはなりません。 <!-- If you do that, and the condition is not handled, --> <!-- the stack trace will halt at the point of the resignal, --> <!-- hiding the rest. --> もしそうした場合、コンディションが始末されないと、 スタックトレースは、再通知された地点で停止し、 残りを隠してしまいます。 And the rest is the part we really care about! <BAD_CODE_SNIPPET> ;; 悪い例 (handler-case (catch 'ticket-at (etd-process-blocks)) (error (c) (reset-parser-values) (error c))) </BAD_CODE_SNIPPET> <CODE_SNIPPET> ;; 良い例 (unwind-protect (catch 'ticket-at (etd-process-blocks)) (reset-parser-values)) </CODE_SNIPPET>
<p> <!-- Using <code>(declare (type ...))</code> --> <!-- is the least-desirable mechanism to use --> <!-- because, as Scott McKay puts it: --> <code>(declare (type ...))</code>の使用は、 最低限にすることが望ましいです。その理由については、 Scott McKayによって説明されています。 </p> <blockquote> <p> <!-- The fact is, <code>(declare (type ...))</code> does different things --> <!-- depending on the compiler settings of speed, safety, etc. --> 実際のところ、<code>(declare (type ...))</code>は コンパイラ設定のspeedや、safetyの設定に依存している。
<!-- In some compilers, when speed is greater than safety, --> <!-- <code>(declare (type ...))</code> will tell the compiler --> <!-- "please assume that these variables have these types" --> <!-- <em>without</em> generating any type-checks. --> いくつかのコンパイラはsafetyよりspeedを優先した場合、 <code>(declare (type ...))</code> を、コンパイラに対する 「これらの変数はこれらの型だと信用してください」 というメッセージとし、いくつかの型判定を<em>しない</em>ために使います。
<!-- That is, if some variable has the value <code>1432</code> in it, --> <!-- and you declare it to be of type <code>string</code>, --> <!-- the compiler might just go ahead and use it as though it's a string. --> 例えば、ある変数が値<code>1432</code>を持ち、 あなたがその型を<code>string</code>として宣言すると、 コンパイラはそれを文字列と見做して使用します。 </p> <p> <!-- Moral: don't use <code>(declare (type ...))</code> --> <!-- to declare the contract of any API functions, --> <!-- it's not the right thing. --> 良識:<code>(declare (type ...))</code>を、 なんらかのAPI関数の契約として使ってはいけません。 それはうまいやり方ではありません。 <!-- Sure, use it for "helper" functions, but not API functions. --> もちろん、ヘルパー関数のためには使えますが、API関数のために使ってはいけません。 </p> </blockquote>
<!-- You must not use MOP "intercessory" operations at runtime. --> <!-- You should not use MOP "intercessory" operations at compile-time. --> <!-- At runtime, they are at worst a danger, at best a performance issue. --> <!-- At compile-time, it is usually cleaner that --> <!-- macros should set things up the right way in one pass --> <!-- than have to require a second pass of fixups through intercession; --> <!-- but sometimes, fixups are necessary to resolve forward references, --> <!-- and intercession is allowed then. --> <!-- MOP intercession is a great tool for interactive development, --> <!-- and you may enjoy it while developping and debugging; --> <!-- but you should not use it in normal applications. --> MOPのintercessory(仲裁的)オペレーション[訳注:intercessionは技術用語で、 プログラムの構成要素を調べる(introspection)ことに対して、その構成要素を変更することを指します (出典: <a href="http://bc.tech.coop/blog/050919.html">http://bc.tech.coop/blog/050919.html</a>)。 このようなオペレータの例としては、<code>defclass</code>の内部で使われる<code>COMPUTE-CLASS-PRECEDENCE-LIST</code> や<code>DEFMETHOD</code>の内部で使われる<code>ADD-METHOD</code>等があります。]を実行時に使用してはなりません。 MOPの"intercessory"オペレーターをコンパイル時に使用してもなりません。 実行時では、最悪の場合、危険を犯すことになり、良くてもパフォーマンス上の問題があります。 コンパイル時では、通常、しかるべきマクロで事を正しく1パスで行う方が、2パス目が必要となるintercessionによる対処より簡潔です。 しかし、前方参照の解決のための対処が必要なこともあるでしょう。そのときにはintercessionの利用も許されま MOPのintercessionは、対話的開発では素晴らしい道具ですし、開発中とデバッグ中は、楽しんで使うことができるでしょうが、 通常のアプリケーション内でこれを利用するべきではありません。 <!-- MOPのintercession/introspectionについては http://bc.tech.coop/blog/050919.html 簡単に言うとintrospectionは classのメタ情報の読み出し intercessionは class への書き込み・変更 [ラテン語「…の間へ行く」の意 (INTER-+cēdere ‘go'); 【名詞】 intercession] by weblio -->
<!-- <CATEGORY title="Meta-language guidelines"> --> <CATEGORY title="メタ言語ガイドライン"> <!-- <STYLEPOINT title="Macros"> --> <STYLEPOINT title="マクロ"> <SUMMARY> <!-- Use macros when appropriate, which is often. --> <!-- Define macros when appropriate, which is seldom. --> マクロを使うことは多いですが、適切な場合に利用しましょう。 それほど多くありませんが、それが適切な場合にはマクロを定義しましょう。 </SUMMARY> <BODY> <p> <!-- Macros bring syntactic abstraction, which is a wonderful thing. --> <!-- It helps make your code clearer, by describing your intent --> <!-- without getting bogged in implementation details --> <!-- (indeed abstracting those details away). --> <!-- It helps make your code more concise and more readable, --> <!-- by eliminating both redundancy and irrelevant details. --> <!-- But it comes at a cost to the reader, --> <!-- which is learning a new syntactic concept for each macro. --> <!-- And so it should not be abused. --> マクロは構文的抽象をもたらし、これは素晴らしいことです。 実装の詳細に囚われることなく意図を記述することを可能にし、コードを明確にするのを助けます(まさにそれらの詳細を抽象化します)。 冗長であったり、無関係であったりする詳細のどちらも省くことで、より簡潔に、より読みやすくすることを助けます。 しかし、マクロごとに新しい構文概念の学習という読み手への負担をもたらします。 それ故にマクロは乱用すべきではありません。 </p> <p> <!-- The general conclusion is that there shouldn't be --> <!-- any recognizable <em>design pattern</em> --> <!-- in a good Common Lisp program. --> <!-- The one and only pattern is: <em>use the language</em>, --> <!-- which includes defining and using syntactic abstractions. --> 一般的結論として、良いCommon Lispのプログラムの中に、何か<em>デザイン・パターン</em>とされるようなものはない筈です。 <em>言語を使う</em>のが唯一のパターンであり、これは構文的抽象化の定義と利用を含みます。 </p>
The general conclusion is that there shouldn't be any recognizable design pattern in a good Common Lisp program. The one and only pattern is: use the language, which includes defining and using syntactic abstractions.
This should be a quote.
Name:
Anonymous2015-07-02 5:48
LISP is a mental attitude rather than a programming language. It uses a certain process of the mind expressed spontaneously through keyboard. I'm concerned with retaining that process.
LISP is an open-ended programming language for open minds.
Anyone can learn Lisp in a few minutes, but nobody could master lisping in a thousand years.
It bugs me when people try to analyze Lisp as a mathematical theorem. It's not. It's feeling.
Lisp, for me, has always been a place where anything is possible--a refuge, a magical world where anyone can go, where all kinds of people can come together, and anything can happen. We are limited only by our imagination.
I hate static languages. I have to change language to my own way of doing it. That's all I know.
One thing I like about Lisp, kid, is that I don't know what's going to happen next. Do you?
The whole thing of programming LISP is not to control it but to be swept away by it. If you're swept away by it you can't wait to do it again and the same magical moments always come.
My own feelings about the direction in which LISP should go are that there should be much less stress on static exhibitionism and much more on dynamic content, on what might be termed humanity in programming and the freedom to express all that you want.
Not to deny that LISP is a thinking people's programming language, but when I'm lisping if I ever catch myself thinking, I'm in trouble--I know something is wrong.
Lispness is not a state of mind, It's a fact of life!
Surrender your whole being to LISP, and gravity disappears...with few macros, one could write code as deep as the ocean.
Macros are to Lisp what yeast is to bread--without it, it's flat.
Recursion is the ability to talk to oneself.
Making the simple complicated is commonplace; making the complicated simple, awesomely simple, that's creativity. — Charles Mingus
Lisp is your own experience, your thoughts, your wisdom. If you don't live it, it won't come out of your REPL.
It is becoming increasingly difficult to decide where LISP starts or where it ends, or even where the borderline lies between between programming in general and LISP. I feel there is no boundary line.
LISP is what we need when other languages fail us, but we cannot remain silent.
<SUMMARY> <!-- You must not use <code>EVAL</code> at runtime. --> 実行時に<code>EVAL</code>を使ってはなりません。 </SUMMARY> <BODY> <p> <!-- Places where it is actually appropriate to use <code>EVAL</code> --> <!-- are so few and far between that you must consult with your reviewers; --> <!-- it's easily misused. --> <code>EVAL</code>を使うことが真に適切であるという極まれな場面でも、 あなたはあなたの査読者と相談しなければなりません。 EVALは容易に誤用されるからです。 </p> <p> <!-- If your code manipulates symbols at runtime --> <!-- and needs to get the value of a symbol, --> <!-- use <code>SYMBOL-VALUE</code>, not <code>EVAL</code>. --> もしもあなたのコードが、実行時にシンボルを操作し、 シンボルの値を取得することを必要とするときは <code>EVAL</code>ではなく<code>SYMBOL-VALUE</code>を使いましょう。 </p> <p> <!-- Often, what you really need is to write a macro, --> <!-- not to use <code>EVAL</code>. --> 良くあること: あなたが本当に必要としていることは「マクロを書く」ことで「<code>EVAL</code>を使う」ことではありません。 </p> <p> <!-- You may be tempted to use <code>EVAL</code> as a shortcut --> <!-- to evaluating expressions in a safe subset of the language. --> 言語の安全なサブセット内において、式を評価するときの近道として、<code>EVAL</code> を利用する誘惑にかられるかもしれません。 <!-- But it often requires more scrutiny to properly check and sanitize --> <!-- all possible inputs to such use of <code>EVAL</code> --> <!-- than to build a special-purpose evaluator. --> <!-- You must not use <code>EVAL</code> in this way at runtime. --> しかし、大抵の場合、特殊用途の評価器をつくりあげるよりも<code>EVAL</code>を使う方が、 すべての入力の可能性について有効性と安全を保つための監視の手間が増えます。 このような場合、<code>EVAL</code>は使わないようにしないとなりません。 </p> <p> <!-- Places where it is OK to use <code>EVAL</code> are: --> <code>EVAL</code>を使うことが許される状況を以下に記します。 </p> <ul> <li> <!-- The implementation of an interactive development tool. --> インタラクティブな開発ツールの実装。 </li> <li> <!-- The build infrastructure. --> 基盤の構築。 </li> <li> <!-- Backdoors that are part of testing frameworks. --> <!-- (You MUST NOT have such backdoors in production code.) --> テストフレームワークにおけるバックドア (実用コードにおいてこの手のバックドアを設けてはなりません)。 </li> <li> <!-- Macros that fold constants at compile-time. --> コンパイル時に定数をたたみ込むマクロ。 </li> <li> <!-- Macros that register definitions to meta-data structures; --> メタデータ構造のための定義を登録するマクロ。 <!-- the registration form is sometimes evaluated at compile-time --> <!-- as well as included in the macro-expansion, --> <!-- so it is immediately available to other macros. --> 登録を行うフォームは時にコンパイル時に評価、もしくは、マクロ展開で組み込まれるので、 即座に他のマクロから利用可能になります。 </li> </ul> <p> <!-- Note that in the latter case, --> <!-- if the macro isn't going to be used at the top-level, --> <!-- it might not be possible to make these definitions available --> <!-- as part of the expansion. --> <!-- g000001: なんとなく分かりますが具体的にどういうコードになるのか想像できないですね --> 注記: 後の例<!-- マクロ展開時のことを指している? g000001 -->において、もしマクロがトップレベルで使用できる状態にならない場合、 展開の一部分である定義が展開されず、[結果として]それらの定義も有効にならない可能性があるということに注意が必要です。 <!-- The same phenomenon may happen in a <code>DEFTYPE</code> expansion, --> <!-- or in helper functions used by macros. --> 同じような現象は<code>DEFTYPE</code>での展開や、 マクロに利用されるヘルパ関数においても起こります。 <!-- In these cases, you may actually have to use --> <!-- <code>ASDF-FINALIZERS:EVAL-AT-TOPLEVEL</code> in your macro. --> こういった場合、マクロ内において、 <code>ASDF-FINALIZERS:EVAL-AT-TOPLEVEL</code>を使う必要が実際にあるかもしれません。 <!-- It will not only <code>EVAL</code> your definitions --> <!-- at macro-expansion time for immediate availability, --> <!-- it will also save the form aside, for inclusion in a --> <!-- <code>(ASDF-FINALIZERS:FINAL-FORMS)</code> --> <!-- that you need to include at the end of the file being compiled --> <!-- (or before the form is needed). --> これは、マクロ展開時に、フォームを<code>EVAL</code>し、即時に有効化するだけでなく、 ファイルがコンパイルされる時にファイルの末尾に置く必要があるものとして(もしくは、そのフォームが必要とされる前に)、 <code>(ASDF-FINALIZERS:FINAL-FORMS)</code> が含めるフォームとして取っておきます。 <!-- This way, the side-effects are present when loading the fasl --><!-- faslはコンパイルされてると思うのでfileの間違い?: g000001 --> <!-- without having compiled it as well as while compiling it; --> この方法は、コンパイルしたfasl[ファイル?]においてもしないものにおいても副作用を持っています。 <!-- in either case, the form is made available at load-time. --> どちらの場合も、フォームはロード時に使えるようになります。 <!-- <code>ASDF-FINALIZERS</code> ensures that the form is present, --> <!-- by throwing an error if you omit it. --> <code>ASDF-FINALIZERS</code>はフォームが存在することを保証し、[フォームを]省略した場合はエラーを投げます。 </p> </BODY>
<p> <!-- You must not use <code>INTERN</code> at runtime. --> <!-- Not only does it cons, --> <!-- it either creates a permanent symbol that won't be collected --> <!-- or gives access to internal symbols. --> <!-- This creates opportunities for memory leaks, denial of service attacks, --> <!-- unauthorized access to internals, clashes with other symbols. --> <code>INTERN</code>を実行時に使用してはなりません。 これは[GCに]回収されない恒久的なシンボルの生成であろうと、内部シンボルの生成であろうと良くありません。 <!-- pros and consのconsか、それともはboxingのことか、それとも「construct」の意味か -g000001 --> これらの実行は、メモリリーク・DoS攻撃・内部への不正アクセス・他のシンボルとの競合、等の発生を生む可能性があります。 </p> <p> <!-- You must not <code>INTERN</code> a string --> <!-- just to compare it to a keyword; --> <!-- use <code>STRING=</code> or <code>STRING-EQUAL</code>. --> 単にキーワード[シンボル]を比較するためだけに、文字列を<code>INTERN</code>してはなりません。 <code>STRING=</code>か<code>STRING-EQUAL</code>を使いましょう。 </p> <BAD_CODE_SNIPPET> (member (intern str :keyword) $keys) ; 悪い </BAD_CODE_SNIPPET> <CODE_SNIPPET> (member str $keys :test #'string-equal) ; より良い </CODE_SNIPPET> <p> <!-- You must not use <code>UNINTERN</code> at runtime. --> <!-- It can break code that relies on dynamic binding. --> <!-- It makes things harder to debug. --> <!-- You must not dynamically intern any new symbol, --> <!-- and therefore you need not dynamically unintern anything. --> <code>UNINTERN</code>を実行時に使用してはなりません。 これは、動的な束縛に依存したコードを破壊する可能性があります。 また、これは、デバッグを困難なものにします。 動的に新しいシンボルを<code>INTERN</code>してはなりませんし、そうなると、まったく動的にシンボルを<code>UNINTERN</code>する必要もありません。<!-- un/internは別個>のものでは? -g000001 --> </p> <p> <!-- You may of course use <code>INTERN</code> at compile-time, --> <!-- in the implementation of some macros. --> <!-- Even so, it is usually more appropriate --> <!-- to use abstractions on top of it, such as --> <!-- <code>ALEXANDRIA:SYMBOLICATE</code> or --> <!-- <code>ALEXANDRIA:FORMAT-SYMBOL</code> --> <!-- to create the symbols you need. --> 勿論、コンパイル時には、マクロの組み立ての中で<code>INTERN</code>は使えるでしょう。 とはいえ、大抵は[<code>INTERN</code>を直に使うより]、それを抽象化したものを使うのがより適切であり、 必要なシンボルを生成するのには<code>ALEXANDRIA:SYMBOLICATE</code>や<code>ALEXANDRIA:FORMAT-SYMBOL</code>のようなものを使うことでしょう。 </p>
<p> <!-- Note that with optimizing implementations, such as SBCL or CMUCL, --> <!-- defining constants this way precludes any later redefinition --> <!-- short of <code>UNINTERN</code>ing the symbol --> <!-- and recompiling all its clients. --> SBCLやCMUCLなどの最適化をする処理系ではこのように定数を定義するとシンボルを<code>UNINTERN</code>してしまうため、定数を使っているコード全てを再コンパイルする以外には後 から定数を再定義する方法は無いことを覚えておきましょう。 <!-- This may make it "interesting" to debug things at the REPL --> <!-- or to deploy live code upgrades. --> これによってREPLでのデバッグやホットデプロイが「愉快な」ことになってしまいます。 <!-- If there is a chance that your "constants" are not going to be constant --> <!-- over the lifetime of your server processes --> <!-- after taking into consideration scheduled and unscheduled code patches, --> <!-- you should consider using --> <!-- <code>DEFPARAMETER</code> or <code>DEFVAR</code> instead, --> <!-- or possibly a variant of <code>DEFINE-CONSTANT</code> --> <!-- that builds upon some future library implementing global lexicals --> <!-- rather than <code>DEFCONSTANT</code>. --> もし想定内/外のパッチを考慮するならば、サーバー上で動いている間に「定数」の値が変更され得るなら<code>DEFCONSTANT</code>ではなく<code>DEFPARAMETER</code>や<code>DEFVAR</code>、あるいは[未来のグローバルレキシカル変数の上に実装された|???]<code>DEFINE-CONSTANT</code>の変種の使用を考えるべきです。 <!-- TODO: builds upon some future library implementing global lexicalsの訳が分りませんでした。global lexicals?(κeen) --> <!-- featureなんですかね?。それとも、グローバルなレキシカル変数が実現されることを未来と呼んでいるのか。 なんにしろ無用な修飾の気もしますね…。 g000001 --> <!-- You may keep the <code>+plus+</code> convention in these cases --> <!-- to document the intent of the parameter as a constant. --> この場合は定数として扱う意図であることを示すために<code>+plus+</code>のコーディング規約を一貫して用いることができるでしょう。 </p>