A place to cache linked articles (think custom and personal wayback machine)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761
  1. <!doctype html><!-- This is a valid HTML5 document. -->
  2. <!-- Screen readers, SEO, extensions and so on. -->
  3. <html lang=fr>
  4. <!-- Has to be within the first 1024 bytes, hence before the <title>
  5. See: https://www.w3.org/TR/2012/CR-html5-20121217/document-metadata.html#charset -->
  6. <meta charset=utf-8>
  7. <!-- Why no `X-UA-Compatible` meta: https://stackoverflow.com/a/6771584 -->
  8. <!-- The viewport meta is quite crowded and we are responsible for that.
  9. See: https://codepen.io/tigt/post/meta-viewport-for-2015 -->
  10. <meta name=viewport content="width=device-width,minimum-scale=1,initial-scale=1,shrink-to-fit=no">
  11. <!-- Required to make a valid HTML5 document. -->
  12. <title>Clojure from the ground up: welcome (archive) — David Larlet</title>
  13. <!-- Generated from https://realfavicongenerator.net/ such a mess. -->
  14. <link rel="apple-touch-icon" sizes="180x180" href="/static/david/icons/apple-touch-icon.png">
  15. <link rel="icon" type="image/png" sizes="32x32" href="/static/david/icons/favicon-32x32.png">
  16. <link rel="icon" type="image/png" sizes="16x16" href="/static/david/icons/favicon-16x16.png">
  17. <link rel="manifest" href="/manifest.json">
  18. <link rel="mask-icon" href="/static/david/icons/safari-pinned-tab.svg" color="#5bbad5">
  19. <link rel="shortcut icon" href="/static/david/icons/favicon.ico">
  20. <meta name="apple-mobile-web-app-title" content="David Larlet">
  21. <meta name="application-name" content="David Larlet">
  22. <meta name="msapplication-TileColor" content="#da532c">
  23. <meta name="msapplication-config" content="/static/david/icons/browserconfig.xml">
  24. <meta name="theme-color" content="#f0f0ea">
  25. <!-- That good ol' feed, subscribe :p. -->
  26. <link rel=alternate type="application/atom+xml" title=Feed href="/david/log/">
  27. <meta name="robots" content="noindex, nofollow">
  28. <meta content="origin-when-cross-origin" name="referrer">
  29. <!-- Canonical URL for SEO purposes -->
  30. <link rel="canonical" href="https://aphyr.com/posts/301-clojure-from-the-ground-up-welcome">
  31. <style>
  32. /* http://meyerweb.com/eric/tools/css/reset/ */
  33. html, body, div, span,
  34. h1, h2, h3, h4, h5, h6, p, blockquote, pre,
  35. a, abbr, address, big, cite, code,
  36. del, dfn, em, img, ins,
  37. small, strike, strong, tt, var,
  38. dl, dt, dd, ol, ul, li,
  39. fieldset, form, label, legend,
  40. table, caption, tbody, tfoot, thead, tr, th, td,
  41. article, aside, canvas, details, embed,
  42. figure, figcaption, footer, header, hgroup,
  43. menu, nav, output, ruby, section, summary,
  44. time, mark, audio, video {
  45. margin: 0;
  46. padding: 0;
  47. border: 0;
  48. font-size: 100%;
  49. font: inherit;
  50. vertical-align: baseline;
  51. }
  52. /* HTML5 display-role reset for older browsers */
  53. article, aside, details, figcaption, figure,
  54. footer, header, hgroup, menu, nav, section { display: block; }
  55. body { line-height: 1; }
  56. blockquote, q { quotes: none; }
  57. blockquote:before, blockquote:after,
  58. q:before, q:after {
  59. content: '';
  60. content: none;
  61. }
  62. table {
  63. border-collapse: collapse;
  64. border-spacing: 0;
  65. }
  66. /* http://practicaltypography.com/equity.html */
  67. /* https://calendar.perfplanet.com/2016/no-font-face-bulletproof-syntax/ */
  68. /* https://www.filamentgroup.com/lab/js-web-fonts.html */
  69. @font-face {
  70. font-family: 'EquityTextB';
  71. src: url('/static/david/css/fonts/Equity-Text-B-Regular-webfont.woff2') format('woff2'),
  72. url('/static/david/css/fonts/Equity-Text-B-Regular-webfont.woff') format('woff');
  73. font-weight: 300;
  74. font-style: normal;
  75. font-display: swap;
  76. }
  77. @font-face {
  78. font-family: 'EquityTextB';
  79. src: url('/static/david/css/fonts/Equity-Text-B-Italic-webfont.woff2') format('woff2'),
  80. url('/static/david/css/fonts/Equity-Text-B-Italic-webfont.woff') format('woff');
  81. font-weight: 300;
  82. font-style: italic;
  83. font-display: swap;
  84. }
  85. @font-face {
  86. font-family: 'EquityTextB';
  87. src: url('/static/david/css/fonts/Equity-Text-B-Bold-webfont.woff2') format('woff2'),
  88. url('/static/david/css/fonts/Equity-Text-B-Bold-webfont.woff') format('woff');
  89. font-weight: 700;
  90. font-style: normal;
  91. font-display: swap;
  92. }
  93. @font-face {
  94. font-family: 'ConcourseT3';
  95. src: url('/static/david/css/fonts/concourse_t3_regular-webfont-20190806.woff2') format('woff2'),
  96. url('/static/david/css/fonts/concourse_t3_regular-webfont-20190806.woff') format('woff');
  97. font-weight: 300;
  98. font-style: normal;
  99. font-display: swap;
  100. }
  101. /* http://practice.typekit.com/lesson/caring-about-opentype-features/ */
  102. body {
  103. /* http://www.cssfontstack.com/ Palatino 99% Win 86% Mac */
  104. font-family: "EquityTextB", Palatino, serif;
  105. background-color: #f0f0ea;
  106. color: #07486c;
  107. font-kerning: normal;
  108. -moz-osx-font-smoothing: grayscale;
  109. -webkit-font-smoothing: subpixel-antialiased;
  110. text-rendering: optimizeLegibility;
  111. font-variant-ligatures: common-ligatures contextual;
  112. font-feature-settings: "kern", "liga", "clig", "calt";
  113. }
  114. pre, code, kbd, samp, var, tt {
  115. font-family: 'TriplicateT4c', monospace;
  116. }
  117. em {
  118. font-style: italic;
  119. color: #323a45;
  120. }
  121. strong {
  122. font-weight: bold;
  123. color: black;
  124. }
  125. nav {
  126. background-color: #323a45;
  127. color: #f0f0ea;
  128. display: flex;
  129. justify-content: space-around;
  130. padding: 1rem .5rem;
  131. }
  132. nav:last-child {
  133. border-bottom: 1vh solid #2d7474;
  134. }
  135. nav a {
  136. color: #f0f0ea;
  137. }
  138. nav abbr {
  139. border-bottom: 1px dotted white;
  140. }
  141. h1 {
  142. border-top: 1vh solid #2d7474;
  143. border-bottom: .2vh dotted #2d7474;
  144. background-color: #e3e1e1;
  145. color: #323a45;
  146. text-align: center;
  147. padding: 5rem 0 4rem 0;
  148. width: 100%;
  149. font-family: 'ConcourseT3';
  150. display: flex;
  151. flex-direction: column;
  152. }
  153. h1.single {
  154. padding-bottom: 10rem;
  155. }
  156. h1 span {
  157. position: absolute;
  158. top: 1vh;
  159. left: 20%;
  160. line-height: 0;
  161. }
  162. h1 span a {
  163. line-height: 1.7;
  164. padding: 1rem 1.2rem .6rem 1.2rem;
  165. border-radius: 0 0 6% 6%;
  166. background: #2d7474;
  167. font-size: 1.3rem;
  168. color: white;
  169. text-decoration: none;
  170. }
  171. h2 {
  172. margin: 4rem 0 1rem;
  173. border-top: .2vh solid #2d7474;
  174. padding-top: 1vh;
  175. }
  176. h3 {
  177. text-align: center;
  178. margin: 3rem 0 .75em;
  179. }
  180. hr {
  181. height: .4rem;
  182. width: .4rem;
  183. border-radius: .4rem;
  184. background: #07486c;
  185. margin: 2.5rem auto;
  186. }
  187. time {
  188. display: bloc;
  189. margin-left: 0 !important;
  190. }
  191. ul, ol {
  192. margin: 2rem;
  193. }
  194. ul {
  195. list-style-type: square;
  196. }
  197. a {
  198. text-decoration-skip-ink: auto;
  199. text-decoration-thickness: 0.05em;
  200. text-underline-offset: 0.09em;
  201. }
  202. article {
  203. max-width: 50rem;
  204. display: flex;
  205. flex-direction: column;
  206. margin: 2rem auto;
  207. }
  208. article.single {
  209. border-top: .2vh dotted #2d7474;
  210. margin: -6rem auto 1rem auto;
  211. background: #f0f0ea;
  212. padding: 2rem;
  213. }
  214. article p:last-child {
  215. margin-bottom: 1rem;
  216. }
  217. p {
  218. padding: 0 .5rem;
  219. margin-left: 3rem;
  220. }
  221. p + p,
  222. figure + p {
  223. margin-top: 2rem;
  224. }
  225. blockquote {
  226. background-color: #e3e1e1;
  227. border-left: .5vw solid #2d7474;
  228. display: flex;
  229. flex-direction: column;
  230. align-items: center;
  231. padding: 1rem;
  232. margin: 1.5rem;
  233. }
  234. blockquote cite {
  235. font-style: italic;
  236. }
  237. blockquote p {
  238. margin-left: 0;
  239. }
  240. figure {
  241. border-top: .2vh solid #2d7474;
  242. background-color: #e3e1e1;
  243. text-align: center;
  244. padding: 1.5rem 0;
  245. margin: 1rem 0 0;
  246. font-size: 1.5rem;
  247. width: 100%;
  248. }
  249. figure img {
  250. max-width: 250px;
  251. max-height: 250px;
  252. border: .5vw solid #323a45;
  253. padding: 1px;
  254. }
  255. figcaption {
  256. padding: 1rem;
  257. line-height: 1.4;
  258. }
  259. aside {
  260. display: flex;
  261. flex-direction: column;
  262. background-color: #e3e1e1;
  263. padding: 1rem 0;
  264. border-bottom: .2vh solid #07486c;
  265. }
  266. aside p {
  267. max-width: 50rem;
  268. margin: 0 auto;
  269. }
  270. /* https://fvsch.com/code/css-locks/ */
  271. p, li, pre, code, kbd, samp, var, tt, time, details, figcaption {
  272. font-size: 1rem;
  273. line-height: calc( 1.5em + 0.2 * 1rem );
  274. }
  275. h1 {
  276. font-size: 1.9rem;
  277. line-height: calc( 1.2em + 0.2 * 1rem );
  278. }
  279. h2 {
  280. font-size: 1.6rem;
  281. line-height: calc( 1.3em + 0.2 * 1rem );
  282. }
  283. h3 {
  284. font-size: 1.35rem;
  285. line-height: calc( 1.4em + 0.2 * 1rem );
  286. }
  287. @media (min-width: 20em) {
  288. /* The (100vw - 20rem) / (50 - 20) part
  289. resolves to 0-1rem, depending on the
  290. viewport width (between 20em and 50em). */
  291. p, li, pre, code, kbd, samp, var, tt, time, details, figcaption {
  292. font-size: calc( 1rem + .6 * (100vw - 20rem) / (50 - 20) );
  293. line-height: calc( 1.5em + 0.2 * (100vw - 50rem) / (20 - 50) );
  294. margin-left: 0;
  295. }
  296. h1 {
  297. font-size: calc( 1.9rem + 1.5 * (100vw - 20rem) / (50 - 20) );
  298. line-height: calc( 1.2em + 0.2 * (100vw - 50rem) / (20 - 50) );
  299. }
  300. h2 {
  301. font-size: calc( 1.5rem + 1.5 * (100vw - 20rem) / (50 - 20) );
  302. line-height: calc( 1.3em + 0.2 * (100vw - 50rem) / (20 - 50) );
  303. }
  304. h3 {
  305. font-size: calc( 1.35rem + 1.5 * (100vw - 20rem) / (50 - 20) );
  306. line-height: calc( 1.4em + 0.2 * (100vw - 50rem) / (20 - 50) );
  307. }
  308. }
  309. @media (min-width: 50em) {
  310. /* The right part of the addition *must* be a
  311. rem value. In this example we *could* change
  312. the whole declaration to font-size:2.5rem,
  313. but if our baseline value was not expressed
  314. in rem we would have to use calc. */
  315. p, li, pre, code, kbd, samp, var, tt, time, details, figcaption {
  316. font-size: calc( 1rem + .6 * 1rem );
  317. line-height: 1.5em;
  318. }
  319. p, li, pre, details {
  320. margin-left: 3rem;
  321. }
  322. h1 {
  323. font-size: calc( 1.9rem + 1.5 * 1rem );
  324. line-height: 1.2em;
  325. }
  326. h2 {
  327. font-size: calc( 1.5rem + 1.5 * 1rem );
  328. line-height: 1.3em;
  329. }
  330. h3 {
  331. font-size: calc( 1.35rem + 1.5 * 1rem );
  332. line-height: 1.4em;
  333. }
  334. figure img {
  335. max-width: 500px;
  336. max-height: 500px;
  337. }
  338. }
  339. figure.unsquared {
  340. margin-bottom: 1.5rem;
  341. }
  342. figure.unsquared img {
  343. height: inherit;
  344. }
  345. @media print {
  346. body { font-size: 100%; }
  347. a:after { content: " (" attr(href) ")"; }
  348. a, a:link, a:visited, a:after {
  349. text-decoration: underline;
  350. text-shadow: none !important;
  351. background-image: none !important;
  352. background: white;
  353. color: black;
  354. }
  355. abbr[title] { border-bottom: 0; }
  356. abbr[title]:after { content: " (" attr(title) ")"; }
  357. img { page-break-inside: avoid; }
  358. @page { margin: 2cm .5cm; }
  359. h1, h2, h3 { page-break-after: avoid; }
  360. p3 { orphans: 3; widows: 3; }
  361. img {
  362. max-width: 250px !important;
  363. max-height: 250px !important;
  364. }
  365. nav, aside { display: none; }
  366. }
  367. ul.with_columns {
  368. column-count: 1;
  369. }
  370. @media (min-width: 20em) {
  371. ul.with_columns {
  372. column-count: 2;
  373. }
  374. }
  375. @media (min-width: 50em) {
  376. ul.with_columns {
  377. column-count: 3;
  378. }
  379. }
  380. ul.with_two_columns {
  381. column-count: 1;
  382. }
  383. @media (min-width: 20em) {
  384. ul.with_two_columns {
  385. column-count: 1;
  386. }
  387. }
  388. @media (min-width: 50em) {
  389. ul.with_two_columns {
  390. column-count: 2;
  391. }
  392. }
  393. .gallery {
  394. display: flex;
  395. flex-wrap: wrap;
  396. justify-content: space-around;
  397. }
  398. .gallery figure img {
  399. margin-left: 1rem;
  400. margin-right: 1rem;
  401. }
  402. .gallery figure figcaption {
  403. font-family: 'ConcourseT3'
  404. }
  405. footer {
  406. font-family: 'ConcourseT3';
  407. display: flex;
  408. flex-direction: column;
  409. border-top: 3px solid white;
  410. padding: 4rem 0;
  411. background-color: #07486c;
  412. color: white;
  413. }
  414. footer > * {
  415. max-width: 50rem;
  416. margin: 0 auto;
  417. }
  418. footer a {
  419. color: #f1c40f;
  420. }
  421. footer .avatar {
  422. width: 200px;
  423. height: 200px;
  424. border-radius: 50%;
  425. float: left;
  426. -webkit-shape-outside: circle();
  427. shape-outside: circle();
  428. margin-right: 2rem;
  429. padding: 2px 5px 5px 2px;
  430. background: white;
  431. border-left: 1px solid #f1c40f;
  432. border-top: 1px solid #f1c40f;
  433. border-right: 5px solid #f1c40f;
  434. border-bottom: 5px solid #f1c40f;
  435. }
  436. </style>
  437. <h1>
  438. <span><a id="jumper" href="#jumpto" title="Un peu perdu ?">?</a></span>
  439. Clojure from the ground up: welcome (archive)
  440. <time>Pour la pérennité des contenus liés. Non-indexé, retrait sur simple email.</time>
  441. </h1>
  442. <section>
  443. <article>
  444. <h3><a href="https://aphyr.com/posts/301-clojure-from-the-ground-up-welcome">Source originale du contenu</a></h3>
  445. <p>This guide aims to introduce newcomers and experienced programmers alike to the
  446. beauty of functional programming, starting with the simplest building blocks of
  447. software. You’ll need a computer, basic proficiency in the command line, a text editor, and an internet connection. By the end of this series, you’ll have a thorough command of the Clojure programming language.</p>
  448. <h2>Who is this guide for?</h2>
  449. <p>Science, technology, engineering, and mathematics are deeply rewarding fields, yet few women enter STEM as a career path. Still more are discouraged by a culture which repeatedly asserts that women lack the analytic aptitude for writing software, that they are not driven enough to be successful scientists, that it’s not cool to pursue a passion for structural engineering. Those few with the talent, encouragement, and persistence to break in to science and tech are discouraged by persistent sexism in practice: the old boy’s club of tenure, being passed over for promotions, isolation from peers, and flat-out assault. This landscape sucks. I want to help change it.</p>
  450. <p><a href="https://twitter.com/WomenWhoCode">Women Who Code</a>, <a href="http://www.pyladies.com/">PyLadies</a>, <a href="http://www.blackgirlscode.com/">Black Girls Code</a>, <a href="http://railsbridge.org/">RailsBridge</a>, <a href="http://www.girlswhocode.com/about-us/">Girls Who Code</a>, <a href="http://www.girldevelopit.com/">Girl Develop It</a>, and <a href="http://www.lambdaladies.com/">Lambda Ladies</a> are just a few of the fantastic groups helping women enter and thrive in software. I wholeheartedly support these efforts.</p>
  451. <p>In addition, I want to help in my little corner of the technical community–functional programming and distributed systems–by making high-quality educational resources available for free. The <a href="/tags/jepsen">Jepsen</a> series has been, in part, an effort to share my enthusiasm for distributed systems with beginners of all stripes–but especially for <a href="http://aphyr.com/posts/275-meritocracy-is-short-sighted">women, LGBT folks, and people of color</a>.</p>
  452. <p>As technical authors, we often assume that our readers are white, that our readers are straight, that our readers are traditionally male. This is the invisible default in US culture, and it’s especially true in tech. People continue to assume on the basis of my software and writing that I’m straight, because well hey, it’s a statistically reasonable assumption.</p>
  453. <p>But I’m <em>not</em> straight. I get called faggot, cocksucker, and sinner. People say they’ll pray for me. When I walk hand-in-hand with my boyfriend, people roll down their car windows and stare. They threaten to beat me up or kill me. Every day I’m aware that I’m the only gay person some people know, and that I can show that not all gay people are effeminate, or hypermasculine, or ditzy, or obsessed with image. That you can be a manicurist or a mathematician or both. Being different, being a stranger in your culture, <a href="http://aphyr.com/posts/274-identity-and-state">comes with all kinds of challenges</a>. I can’t speak to everyone’s experience, but I can take a pretty good guess.</p>
  454. <p>At the same time, in the technical community I’ve found overwhelming warmth and support, from people of <em>all</em> stripes. My peers stand up for me every day, and I’m so thankful–especially you straight dudes–for understanding a bit of what it’s like to be different. I want to extend that same understanding, that same empathy, to people unlike myself. Moreover, I want to reassure everyone that though they may feel different, they <em>do</em> have a place in this community.</p>
  455. <p>So before we begin, I want to reinforce that you <em>can</em> program, that you <em>can</em> do math, that you <em>can</em> design car suspensions and fire suppression systems and spacecraft control software and distributed databases, regardless of what your classmates and media and even fellow engineers think. You don’t have to be white, you don’t have to be straight, you don’t have to be a man. You can grow up never having touched a computer and still become a skilled programmer. Yeah, it’s harder–and yeah, people will give you shit, but that’s not your fault and has nothing to do with your <em>ability</em> or your <em>right</em> to do what you love. All it takes to be a good engineer, scientist, or mathematician is your curiosity, your passion, the right teaching material, and putting in the hours.</p>
  456. <p>There’s nothing in this guide that’s just for lesbian grandmas or just for mixed-race kids; bros, you’re welcome here too. There’s nothing dumbed down. We’re gonna go as deep into the ideas of programming as I know how to go, and we’re gonna do it with everyone on board.</p>
  457. <p>No matter who you are or who people <em>think</em> you are, this guide is for you.</p>
  458. <h2>Why Clojure?</h2>
  459. <p>This book is about how to program. We’ll be learning in Clojure, which is a modern dialect of a very old family of computer languages, called Lisp. You’ll find that many of this book’s ideas will translate readily to other languages; though they may be <a href="http://aphyr.com/posts/266-core-language-concepts">expressed in different ways</a>.</p>
  460. <p>We’re going to explore the nature of syntax, metalanguages, values, references, mutation, control flow, and concurrency. Many languages leave these ideas implicit in the language construction, or don’t have a concept of metalanguages or concurrency at all. Clojure makes these ideas explicit, first-class language constructs.</p>
  461. <p>At the same time, we’re going to defer or omit any serious discussion of static type analysis, hardware, and performance. This is not to say that these ideas aren’t <em>important</em>; just that they don’t fit well within this particular narrative arc. For a deep exploration of type theory I recommend a study in Haskell, and for a better understanding of underlying hardware, learning C and an assembly language will undoubtedly help.</p>
  462. <p>In more general terms, Clojure is a well-rounded language. It offers broad library support and runs on multiple operating systems. Clojure performance is not terrific, but is orders of magnitude faster than Ruby, Python, or Javascript. Unlike some faster languages, Clojure emphasizes <em>safety</em> in its type system and approach to parallelism, making it easier to write correct multithreaded programs. Clojure is <em>concise</em>, requiring very little code to express complex operations. It offers a REPL and dynamic type system: ideal for beginners to experiment with, and well-suited for manipulating complex data structures. A consistently designed standard library and full-featured set of core datatypes rounds out the Clojure toolbox.</p>
  463. <p>Finally, there are some drawbacks. As a compiled language, Clojure is much slower to start than a scripting language; this makes it unsuitable for writing small scripts for interactive use. Clojure is also <em>not</em> well-suited for high-performance numeric operations. Though it is possible, you have to jump through hoops to achieve performance comparable with Java. I’ll do my best to call out these constraints and shortcomings as we proceed through the text.</p>
  464. <p>With that context out of the way, let’s get started by installing Clojure!</p>
  465. <h2>Getting set up</h2>
  466. <p>First, you’ll need a Java Virtual Machine, or JVM, and its associated
  467. development tools, called the JDK. This is the software which <em>runs</em> a Clojure
  468. program. If you’re on Windows, install <a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html">Oracle
  469. JDK 1.7</a>. If you’re on OS X or Linux, you may already have a JDK installed.
  470. In a terminal, try:</p>
  471. <p><code class="block">which javac
  472. </code>
  473. <p>If you see something like</p>
  474. <code class="block">/usr/bin/javac
  475. </code>
  476. <p>Then you’re good to go. If you don’t see any output from that command, install the appropriate
  477. <a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html">Oracle
  478. JDK 1.7</a> for your operating system, or whatever JDK your package manager has available.</p></p>
  479. <p>When you have a JDK, you’ll need <a href="http://leiningen.org">Leiningen</a>,
  480. the Clojure build tool. If you’re on a Linux or OS X computer, the instructions below
  481. should get you going right away. If you’re on Windows, see the Leiningen page
  482. for an installer. If you get stuck, you might want to start with a
  483. <a href="http://blog.teamtreehouse.com/command-line-basics">primer on command line basics</a>.</p>
  484. <p><code class="block">mkdir -p ~/bin
  485. <span class="nb">cd</span> ~/bin
  486. curl -O https://raw.githubusercontent.com/technomancy/leiningen/stable/bin/lein
  487. chmod a+x lein
  488. </code>
  489. <p>Leiningen automatically handles installing Clojure, finding libraries from the
  490. internet, and building and running your programs. We’ll create a new Leiningen
  491. project to play around in:</p>
  492. <code class="block"><span class="nb">cd</span>
  493. lein new scratch
  494. </code>
  495. <p>This creates a new directory in your homedir, called <code>scratch</code>. If you see <code>command not found</code> instead, it means the directory <code>~/bin</code> isn’t registered with your terminal as a place to search for programs. To fix this, add the line</p>
  496. <code class="block"><span class="nb">export </span><span class="nv">PATH</span><span class="o">=</span><span class="s2">"$PATH"</span>:~/bin
  497. </code>
  498. <p>to the file <code>.bash_profile</code> in your home directory, then run <code>source ~/.bash_profile</code>. Re-running <code>lein new scratch</code> should work.</p></p>
  499. <p>Let’s enter that directory, and start using Clojure itself:</p>
  500. <p><code class="block"><span class="nb">cd </span>scratch
  501. lein repl
  502. </code>
  503. <h2>The structure of programs</h2></p>
  504. <p>When you type <code>lein repl</code> at the terminal, you’ll see something like this:</p>
  505. <p><code class="block">aphyr@waterhouse:~/scratch$ lein repl
  506. nREPL server started on port 45413
  507. REPL-y 0.2.0
  508. Clojure 1.5.1
  509. Docs: (doc function-name-here)
  510. (find-doc "part-of-name-here")
  511. Source: (source function-name-here)
  512. Javadoc: (javadoc java-object-or-class-here)
  513. Exit: Control+D or (exit) or (quit)</p>
  514. <p>user=&gt;</code>
  515. <p>This is an interactive Clojure environment called a REPL, for “Read, Evaluate,
  516. Print Loop”. It’s going to <em>read</em> a program we enter, run that program, and
  517. print the results. REPLs give you quick feedback, so they’re a great way to
  518. explore a program interactively, run tests, and prototype new ideas.</p></p>
  519. <p>Let’s write a simple program. The simplest, in fact. Type “nil”, and hit enter.</p>
  520. <p><code class="block"><span class="nv">user=&gt;</span> <span class="nv">nil</span>
  521. <span class="nv">nil</span>
  522. </code>
  523. <p><code>nil</code> is the most basic value in Clojure. It represents emptiness,
  524. nothing-doing, not-a-thing. The absence of information.</p>
  525. <code class="block"><span class="nv">user=&gt;</span> <span class="nv">true</span>
  526. <span class="nv">true</span>
  527. <span class="nv">user=&gt;</span> <span class="nv">false</span>
  528. <span class="nv">false</span>
  529. </code>
  530. <p><code>true</code> and <code>false</code> are a pair of special values called <em>Booleans</em>. They mean
  531. exactly what you think: whether a statement is true or false. <code>true</code>, <code>false</code>, and <code>nil</code> form the three poles of the Lisp logical system.</p>
  532. <code class="block"><span class="nv">user=&gt;</span> <span class="mi">0</span>
  533. <span class="mi">0</span>
  534. </code>
  535. <p>This is the number zero. Its numeric friends are <code>1</code>, <code>-47</code>, <code>1.2e-4</code>, <code>1/3</code>,
  536. and so on. We might also talk about <em>strings</em>, which are chunks of text surrounded by double quotes:</p>
  537. <code class="block"><span class="nv">user=&gt;</span> <span class="s">"hi there!"</span>
  538. <span class="s">"hi there!"</span>
  539. </code>
  540. <p><code>nil</code>, <code>true</code>, <code>0</code>, and <code>"hi there!"</code> are all different types of <em>values</em>; the
  541. nouns of programming. Just as one could say “House.” in English, we can write a
  542. program like <code>"hello, world"</code> and it evaluates to itself: the string <code>"hello
  543. world"</code>. But most sentences aren’t just about stating the existence of a thing; they involve <em>action</em>. We need <em>verbs</em>.</p>
  544. <code class="block"><span class="nv">user=&gt;</span> <span class="nv">inc</span>
  545. <span class="o">#</span><span class="nv">&lt;core$inc</span> <span class="nv">clojure.core$inc</span><span class="o">@</span><span class="mi">6</span><span class="nv">f7ef41c&gt;</span>
  546. </code>
  547. <p>This is a verb called <code>inc</code>–short for “increment”. Specifically, <code>inc</code> is a
  548. <em>symbol</em> which <em>points</em> to a verb: <code>#&lt;core$inc clojure.core$inc@6f7ef41c&gt;</code>–
  549. just like the word “run” is a <em>name</em> for the <em>concept</em> of running.</p></p>
  550. <p>There’s a key distinction here–that a signifier, a reference, a label, is not
  551. the same as the signified, the referent, the concept itself. If you write the
  552. word “run” on paper, the ink means nothing by itself. It’s just a symbol. But
  553. in the mind of a reader, that symbol takes on <em>meaning</em>; the idea of running.</p>
  554. <p>Unlike the number 0, or the string “hi”, symbols are references to other
  555. values. when Clojure evaluates a symbol, it looks up that symbol’s meaning.
  556. Look up <code>inc</code>, and you get <code>#&lt;core$inc clojure.core$inc@6f7ef41c&gt;</code>.</p>
  557. <p>Can we refer to the symbol itself, <em>without</em> looking up its meaning?</p>
  558. <p><code class="block"><span class="nv">user=&gt;</span> <span class="ss">'inc</span>
  559. <span class="nv">inc</span>
  560. </code>
  561. <p>Yes. The single quote <code>'</code> <em>escapes</em> a sentence. In programming languages, we call sentences <code>expressions</code> or <code>statements</code>. A quote says “Rather than <em>evaluating</em> this expression’s text, simply return the text itself, unchanged.” Quote a symbol, get a symbol. Quote a number, get a number. Quote anything, and get it back exactly as it came in.</p>
  562. <code class="block"><span class="nv">user=&gt;</span> <span class="ss">'123</span>
  563. <span class="mi">123</span>
  564. <span class="nv">user=&gt;</span> <span class="o">'</span><span class="s">"foo"</span>
  565. <span class="s">"foo"</span>
  566. <span class="nv">user=&gt;</span> <span class="o">'</span><span class="p">(</span><span class="mi">1</span> <span class="mi">2</span> <span class="mi">3</span><span class="p">)</span>
  567. <span class="p">(</span><span class="mi">1</span> <span class="mi">2</span> <span class="mi">3</span><span class="p">)</span>
  568. </code>
  569. <p>A new kind of value, surrounded by parentheses: the <em>list</em>. LISP originally stood for LISt Processing, and lists are still at the core of the language. In fact, they form the most basic way to compose expressions, or sentences. A list is a single expression which has <em>multiple parts</em>. For instance, this list contains three elements: the numbers 1, 2, and 3. Lists can contain anything: numbers, strings, even other lists:</p>
  570. <code class="block"><span class="nv">user=&gt;</span> <span class="o">'</span><span class="p">(</span><span class="nf">nil</span> <span class="s">"hi"</span><span class="p">)</span>
  571. <span class="p">(</span><span class="nf">nil</span> <span class="s">"hi"</span><span class="p">)</span>
  572. </code>
  573. <p>A list containing two elements: the number 1, and a second list. That list
  574. contains two elements: the number 2, and another list. <em>That</em> list contains two
  575. elements: 3, and an empty list.</p>
  576. <code class="block">user=&gt; '(1 (2 (3 ())))
  577. (1 (2 (3 ())))</code>
  578. <p>You could think of this structure as a tree–which is a provocative idea,
  579. because <em>languages</em> are like trees too: sentences are comprised of clauses, which can be nested, and each clause may have subjects modified by adjectives, and verbs modified by adverbs, and so on. “Lindsay, my best friend, took the dog which we found together at the pound on fourth street, for a walk with her mother Michelle.”</p>
  580. <code class="block">Took
  581. Lindsay
  582. my best friend
  583. the dog
  584. which we found together
  585. at the pound
  586. on fourth street
  587. for a walk
  588. with her mother
  589. Michelle</code>
  590. <p>But let’s try something simpler. Something we know how to talk about.
  591. “Increment the number zero.” As a tree:</p>
  592. <code class="block">Increment
  593. the number zero</code>
  594. <p>We have a symbol for incrementing, and we know how to write the number zero.
  595. Let’s combine them in a list:</p>
  596. <code class="block"><span class="nv">clj=&gt;</span> <span class="o">'</span><span class="p">(</span><span class="nb">inc </span><span class="mi">0</span><span class="p">)</span>
  597. <span class="p">(</span><span class="nb">inc </span><span class="mi">0</span><span class="p">)</span>
  598. </code>
  599. <p>A basic sentence. Remember, since it’s quoted, we’re talking about the tree,
  600. the text, the expression, by itself. Absent interpretation. If we remove the
  601. single-quote, Clojure will <em>interpret</em> the expression:</p>
  602. <code class="block"><span class="nv">user=&gt;</span> <span class="p">(</span><span class="nb">inc </span><span class="mi">0</span><span class="p">)</span>
  603. <span class="mi">1</span>
  604. </code>
  605. <p>Incrementing zero yields one. And if we wanted to increment <em>that</em> value?</p>
  606. <code class="block">Increment
  607. increment
  608. the number zero</code><code class="block"><span class="nv">user=&gt;</span> <span class="p">(</span><span class="nb">inc </span><span class="p">(</span><span class="nb">inc </span><span class="mi">0</span><span class="p">))</span>
  609. <span class="mi">2</span>
  610. </code>
  611. <p>A sentence in Lisp is a list. It starts with a verb, and is followed by zero or
  612. more objects for that verb to act on. Each part of the list can <em>itself</em> be
  613. another list, in which case that nested list is evaluated first, just like a
  614. nested clause in a sentence. When we type</p>
  615. <code class="block"><span class="p">(</span><span class="nb">inc </span><span class="p">(</span><span class="nb">inc </span><span class="mi">0</span><span class="p">))</span>
  616. </code>
  617. <p>Clojure first looks up the meanings for the symbols in the code:</p>
  618. <code class="block"><span class="p">(</span><span class="o">#</span><span class="nv">&lt;core$inc</span> <span class="nv">clojure.core$inc</span><span class="o">@</span><span class="mi">6</span><span class="nv">f7ef41c&gt;</span>
  619. <span class="p">(</span><span class="o">#</span><span class="nv">&lt;core$inc</span> <span class="nv">clojure.core$inc</span><span class="o">@</span><span class="mi">6</span><span class="nv">f7ef41c&gt;</span>
  620. <span class="mi">0</span><span class="p">))</span>
  621. </code>
  622. <p>Then evaluates the innermost list <code>(inc 0)</code>, which becomes the number 1:</p>
  623. <code class="block"><span class="p">(</span><span class="o">#</span><span class="nv">&lt;core$inc</span> <span class="nv">clojure.core$inc</span><span class="o">@</span><span class="mi">6</span><span class="nv">f7ef41c&gt;</span>
  624. <span class="mi">1</span><span class="p">)</span>
  625. </code>
  626. <p>Finally, it evaluates the outer list, incrementing the number 1:</p>
  627. <code class="block"><span class="mi">2</span>
  628. </code>
  629. <p>Every list starts with a verb. Parts of a list are evaluated from left to
  630. right. Innermost lists are evaluated before outer lists.</p>
  631. <code class="block"><span class="p">(</span><span class="nb">+ </span><span class="mi">1</span> <span class="p">(</span><span class="nb">- </span><span class="mi">5</span> <span class="mi">2</span><span class="p">)</span> <span class="p">(</span><span class="nb">+ </span><span class="mi">3</span> <span class="mi">4</span><span class="p">))</span>
  632. <span class="p">(</span><span class="nb">+ </span><span class="mi">1</span> <span class="mi">3</span> <span class="p">(</span><span class="nb">+ </span><span class="mi">3</span> <span class="mi">4</span><span class="p">))</span>
  633. <span class="p">(</span><span class="nb">+ </span><span class="mi">1</span> <span class="mi">3</span> <span class="mi">7</span><span class="p">)</span>
  634. <span class="mi">11</span>
  635. </code>
  636. <p>That’s it.</p></p>
  637. <p>The entire grammar of Lisp: the structure for every expression in the language.
  638. We transform expressions by <em>substituting</em> meanings for symbols, and obtain
  639. some result. This is the core of the <a href="http://en.wikipedia.org/wiki/Lambda_calculus">Lambda Calculus</a>, and it is the theoretical basis for almost all computer languages.
  640. Ruby, Javascript, C, Haskell; all languages express the text of their programs in different ways, but internally all construct a <em>tree</em> of expressions. Lisp simply makes it explicit.</p>
  641. <h2>Review</h2>
  642. <p>We started by learning a few basic nouns: numbers like <code>5</code>, strings like
  643. <code>"cat"</code>, and symbols like <code>inc</code> and <code>+</code>. We saw how quoting makes the
  644. difference between an <em>expression</em> itself and the thing it <em>evaluates</em> to. We
  645. discovered symbols as <em>names</em> for other values, just like how words represent
  646. concepts in any other language. Finally, we combined lists to make trees, and
  647. used those trees to represent a program.</p>
  648. <p>With these basic elements of syntax in place, it’s time to expand our
  649. vocabulary with new verbs and nouns; learning to <a href="http://aphyr.com/posts/302-clojure-from-the-ground-up-basic-types">represent more complex values and transform them in different ways</a>.</p>
  650. </article>
  651. </section>
  652. <nav id="jumpto">
  653. <p>
  654. <a href="/david/blog/">Accueil du blog</a> |
  655. <a href="https://aphyr.com/posts/301-clojure-from-the-ground-up-welcome">Source originale</a> |
  656. <a href="/david/stream/2019/">Accueil du flux</a>
  657. </p>
  658. </nav>
  659. <footer>
  660. <div>
  661. <img src="/static/david/david-larlet-avatar.jpg" loading="lazy" class="avatar" width="200" height="200">
  662. <p>
  663. Bonjour/Hi!
  664. Je suis <a href="/david/" title="Profil public">David&nbsp;Larlet</a>, je vis actuellement à Montréal et j’alimente cet espace depuis 15 ans. <br>
  665. Si tu as apprécié cette lecture, n’hésite pas à poursuivre ton exploration. Par exemple via les <a href="/david/blog/" title="Expériences bienveillantes">réflexions bimestrielles</a>, la <a href="/david/stream/2019/" title="Pensées (dés)articulées">veille hebdomadaire</a> ou en t’abonnant au <a href="/david/log/" title="S’abonner aux publications via RSS">flux RSS</a> (<a href="/david/blog/2019/flux-rss/" title="Tiens c’est quoi un flux RSS ?">so 2005</a>).
  666. </p>
  667. <p>
  668. Je m’intéresse à la place que je peux avoir dans ce monde. En tant qu’humain, en tant que membre d’une famille et en tant qu’associé d’une coopérative. De temps en temps, je fais aussi des <a href="https://github.com/davidbgk" title="Principalement sur Github mais aussi ailleurs">trucs techniques</a>. Et encore plus rarement, <a href="/david/talks/" title="En ce moment je laisse plutôt la place aux autres">j’en parle</a>.
  669. </p>
  670. <p>
  671. Voici quelques articles choisis :
  672. <a href="/david/blog/2019/faire-equipe/" title="Accéder à l’article complet">Faire équipe</a>,
  673. <a href="/david/blog/2018/bivouac-automnal/" title="Accéder à l’article complet">Bivouac automnal</a>,
  674. <a href="/david/blog/2018/commodite-effondrement/" title="Accéder à l’article complet">Commodité et effondrement</a>,
  675. <a href="/david/blog/2017/donnees-communs/" title="Accéder à l’article complet">Des données aux communs</a>,
  676. <a href="/david/blog/2016/accompagner-enfant/" title="Accéder à l’article complet">Accompagner un enfant</a>,
  677. <a href="/david/blog/2016/senior-developer/" title="Accéder à l’article complet">Senior developer</a>,
  678. <a href="/david/blog/2016/illusion-sociale/" title="Accéder à l’article complet">L’illusion sociale</a>,
  679. <a href="/david/blog/2016/instantane-scopyleft/" title="Accéder à l’article complet">Instantané Scopyleft</a>,
  680. <a href="/david/blog/2016/enseigner-web/" title="Accéder à l’article complet">Enseigner le Web</a>,
  681. <a href="/david/blog/2016/simplicite-defaut/" title="Accéder à l’article complet">Simplicité par défaut</a>,
  682. <a href="/david/blog/2016/minimalisme-esthetique/" title="Accéder à l’article complet">Minimalisme et esthétique</a>,
  683. <a href="/david/blog/2014/un-web-omni-present/" title="Accéder à l’article complet">Un web omni-présent</a>,
  684. <a href="/david/blog/2014/manifeste-developpeur/" title="Accéder à l’article complet">Manifeste de développeur</a>,
  685. <a href="/david/blog/2013/confort-convivialite/" title="Accéder à l’article complet">Confort et convivialité</a>,
  686. <a href="/david/blog/2013/testament-numerique/" title="Accéder à l’article complet">Testament numérique</a>,
  687. et <a href="/david/blog/" title="Accéder aux archives">bien d’autres…</a>
  688. </p>
  689. <p>
  690. On peut <a href="mailto:david%40larlet.fr" title="Envoyer un courriel">échanger par courriel</a>. Si éventuellement tu souhaites que l’on travaille ensemble, tu devrais commencer par consulter le <a href="http://larlet.com">profil dédié à mon activité professionnelle</a> et/ou contacter directement <a href="http://scopyleft.fr/">scopyleft</a>, la <abbr title="Société coopérative et participative">SCOP</abbr> dont je fais partie depuis six ans. Je recommande au préalable de lire <a href="/david/blog/2018/cout-site/" title="Attention ce qui va suivre peut vous choquer">combien coûte un site</a> et pourquoi je suis plutôt favorable à une <a href="/david/pro/devis/" title="Discutons-en !">non-demande de devis</a>.
  691. </p>
  692. <p>
  693. Je ne traque pas ta navigation mais mon
  694. <abbr title="Alwaysdata, 62 rue Tiquetonne 75002 Paris, +33.184162340">hébergeur</abbr>
  695. conserve des logs d’accès.
  696. </p>
  697. </div>
  698. </footer>
  699. <script type="text/javascript">
  700. ;(_ => {
  701. const jumper = document.getElementById('jumper')
  702. jumper.addEventListener('click', e => {
  703. e.preventDefault()
  704. const anchor = e.target.getAttribute('href')
  705. const targetEl = document.getElementById(anchor.substring(1))
  706. targetEl.scrollIntoView({behavior: 'smooth'})
  707. })
  708. })()
  709. </script>