57 Matching Annotations
  1. Feb 2019
    1. :ok

      nice, return value: keyword!

    2. (fn [system] (throw (ex-info "initializer not set, did you call `set-init`?" {}))))

      interesting pattern, default function throws kind of like abstract base classes methods in python

  2. Dec 2018
    1. Full disclosure: I’m a co-maintainer of clj-time and I’m pretty vocal about encouraging people not to use clj-time when starting a new project: use Java Time instead. Conversion from an existing, clj-time-heavy project is another matter tho’, unfortunately.

      sean cornfield co-mainainter of clj-time use Java.Time

  3. Nov 2018
    1. Meditation can not only provide a welcome counterweight to this work with abstractions, it also cultives 10 qualities of character (Pali: paramis) that are useful during the practice of programming.

      Generosity Morality Renunciation Understanding Effort Patience/tolerance Truthfulness Loving-kindness Equanimity

    1. One quick trick for making it easier for debugging/understanding your threading macros is to put print statements in between some of the steps. The important thing to remember is that all the print functions in clojure return nil so you need to make a little helper function (I like to call mine ?) that prints and then returns the original input, like this: (defn ? [x] (prn x) x)

      debugging trick

    2. I don't think passing the entire http client is very idiomatic, but what is quite common is to pass the entire "environment" (aka runtime configuration) that your app needs through every function. In your case if the only variant is the URL then you could just pass the URL as the first parameter to get-data. This might seem cumbersome to someone used to OO programming but in functional programming it's quite standard. You might notice when looking at example code, tutorials, open source libraries etc. that almost all code that reads or writes to databases expects the DB connection information (or an entire db object) as a parameter to every single function. Another thing you often see is an entire "env" map being passed around which has all config in it such as endpoint URLs.

      passing state down the call stack configuration, connection, db--pretty common in FP

    3. Something that I've found helps greatly with testing is that when you have code with lots of nested function calls you should try to refactor it into a flat, top level pipeline rather than a calling each function from inside its parent function. Luckily in clojure this is really easy to do with macros like -> and friends, and once you start embracing this approach you can enter a whole new world of transducers. What I mean by a top level pipeline is that for example instead of writing code like this: (defn remap-keys [data] ...some logic...) (defn process-data [data] (remap-keys (flatten data))) (defn get-data [] (let [data (http/get *url*)] (process-data data))) you should make each step its own pure function which receives and returns data, and join them all together at the top with a threading macro: (defn fetch-data [url] (http/get url)) (defn process-data [data] (flatten data)) (defn remap-keys [data] ...some logic...) (defn get-data [] (-> *url* fetch-data process-data remap-keys)) You code hasn't really changed, but now each function can be tested completely independently of the others, because each one is a pure data transform with no internal calls to any of your other functions. You can use the repl to run each step one at a time and in doing so also capture some mock data to use for your tests! Additionally you could make an e2e tests pipeline which runs the same code as get-data but just starts with a different URL, however I would not advise doing this in most cases, and prefer to pass it as a parameter (or at least dynamic var) when feasible.

      testing flat no deep call stacks, use pipelines

    4. One thing Component taught me was to think of the entire system like an Object. Specifically, there is state that needs to be managed. So I suggest you think about -main as initializing your system state. Your system needs an http client, so initialize it before you do anything else

      software design state on the outside, before anything else lessions from Component

    5. For the sweet spot you're looking for, I suggest being clear about if you're designing or developing. If you're designing and at the REPL, force yourself to step away with pen and paper after you've gotten some fast feedback.

      designing vs developing!

    1. n

      Using the syntax #'a.b/d is a shortcut for (var a.b/d), with returns the "var" which points to the "function" a.b/d. When Clojure sees the var, it automatically substitutes the function before evaluation. I found this (mostly undocumented) behavior quite confusing for several years. – Alan Thompson May 26 '16 at 21:41

    1. Re-open libraries for exploration I use in-ns to jump into library namespaces and re-define their vars. I insert bits of println statements to help understand how data flows through a library. These monkey-patches only exist in the running REPL. I usually put them inside a comment form. On a REPL restart, the library is back at its pristine state. In this example below, I re-open clj-http.headers to add tracing before the header transformation logic: [source] ;; set us up for re-opening libraries (require 'clj-http.headers) (in-ns 'clj-http.headers) (defn- header-map-request [req] (let [req-headers (:headers req)] (if req-headers (do (println "HEADERS: " req-headers) ;; <-- this is my added print (-> req (assoc :headers (into (header-map) req-headers) :use-header-maps-in-response? true))) req))) ;; Go back to to the user namespace to test the change (in-ns 'user) (require '[clj-http.client :as http]) (http/get "http://www.example.com") ;; This is printed in the REPL: ;; HEADERS: {accept-encoding gzip, deflate} An astute observer will notice this workflow is no different from the regular clojure workflow. Clojure gets out of your way and allows you to shape & experiment in the code in the REPL. You can use this technique to explore clojure.core too!

      explore library code in the repl in-ns and the redefinition

    2. Unmap namespaces during experimentation I use ns-unmap and ns-unalias to remove definitions from my namespace. These are the complementary functions of require and def. While exploring, you namespace will accrue failed experiments, especially around naming. Instead of using a giant hammer [tools.namespace], you can opt for finer-grained tools like these. Example: (require '[clojure.string :as thing]) (ns-unalias *ns* 'thing) ; *ns* refers to the current namespace

      cleaning up the namespace fro repl experimentation

    1. But hey, we're not running Windows 95 anymore! The current branch of windows is based on Windows NT, not Win95. But Windows NT wanted compatibility with DOS/Windows programs. And XP merged the two lines. So these special files still work, FORTY FOUR FUCKING YEARS LATER

      special files today 44 years later--backwards compatibility

    2. This idea was brought into CP/M by Gary Kiddal in 1974. You could do neat things with it like copy data off the serial port into a text file, or print a textfile right from the command line! This is done in unix by having special files existing in special folders, like /dev/tty for the console or /dev/lp0 for the first printer. You can get infinite zeros from /dev/zero, random bytes from /dev/random, etc! but here's the problem: CP/M is designed for 8-bit computers with very little memory, and no hard drives. At best you've got an 8" floppy drive. So directories? you don't need 'em. Instead of directories, you just use different disks. but without directories you can't put all your special files over in a /dev/ directory. So they're just "everywhere", effectively. So if you have FOO.TXT and need to print it, you can do "PIP LST:=FOO.TXT" which copies foo.txt to the "file" LST, which is the printer. and it works where ever you are, because there are no directories! it's simple. but what about extensions? Here's the problem: programs like to name their files with the right extension. so if you're running a program and it goes "ENTER FILENAME TO SAVE LISTING TO" you could tell it LST to print it or PTP to punch it out to tape (cause it's 1974, remember?) but the program might try to put .TXT on the end of your filename! LST.TXT isn't the printer, right? Nah. It is. These special devices exist at all extensions, so that this works. so if "CON" is reserved to refer to the keyboard, so is CON.TXT and CON.WAT and CON.BUG

      special files in cp/m

    1. That is using a specific tool for a specific use case. You don’t actually have a table view of your data. Once it’s in a table, man, you’re good. That is the modeling. A sequel database table, you have this amazing high-level language for doing all sorts of cool operations with it.To turn this into some class hierarchy, it’s almost criminal. There, I said it. It’s like you’re throwing away the power that you have.

      about a situation when you sometime want an is-a relationship but in most cases just have it as loosely structured (table-like) data format

    1. in general, clojure doesn't have java interop, it has jvm interop so in places where the java language doesn't map 1:1 to the jvm, clojure gives something that matches the raw jvm, not something that matches the java language

      jvm not java interop

    2. clone the repo, then lein install and use whatever that snapshot version in project.clj is where you want to use it (edited)

      how to use specific version of library you can also use checkouts where you just symlink to a local copy from your-project/checkouts

    1. This means that software that deals with Internet must be actively maintained. If it is not it will become more and more useless in practice over time, however much it remains theoretically correct, not because it has bugs or security holes as such but because the environment it was designed to work in no longer exists and thus the assumptions it was built on are now incorrect.

      internet software decays

    1. I update from within Spacemacs by opening a file from .emacs.d, usually the readme file.SPC g s to open Magit client, F to bring up the pull menu, -r to set rebase to true, o to pull from origin.  Then I restart Spacemacs with SPC q r.Then I update the .spacemacs file from template.  And then update packages from the link on the Spacemacs home buffer SPC b h (edited)

      update procedure for spacemacs

  4. Oct 2018
    1. If you haven't experienced the glory of wool, get this shirt. I wear it every day for at least two to three weeks before washing it, stains magically disappear (I've already spilled chocolate on this one, haven't washed it yet, and there's no sign), doesn't ever smell bad, dries quickly, etc. Honestly, wearing cotton strikes me as a bit barbaric.

      wear wool

    2. I've been more or less a nomad since 2008, and was one of the very first to really travel in a minimalist (one small backpack) way. I'm sure others came before me (and my friend Todd), but none I'm aware of who were writing about it.

      first nomad, yeah!

    1. Engelbart embedded a set of organizing principles in his lab, which he termed "bootstrapping strategy".
    2. Engelbart's career was inspired in December 1950 when he was engaged to be married and realized he had no career goals other than "a steady job, getting married and living happily ever after".[14] Over several months he reasoned that: he would focus his career on making the world a better place[15] any serious effort to make the world better would require some kind of organized effort that harnessed the collective human intellect of all people to contribute to effective solutions. if you could dramatically improve how we do that, you'd be boosting every effort on the planet to solve important problems – the sooner the better computers could be the vehicle for dramatically improving this capability.[14]

      Engelbart's guiding philosophy

    1. In computer programming, it doesn’t have a very complex definition. It just means that you represent a thing as part of your data model.

      definition of reify in compsci

    1. A lot of this would be a non issue if we had end user programming. The problem today is that 'configurability' is itself something the programmer needs to implement

      acme example rob pike apparently had an elaborate answer as to why he wouldn't allow to change the colorschme

    2. Configuration knowledge is anti-knowledge -- learning how to conform to the inessential quirks of a system somebody else made up

      good take on configuration

    3. 1 reply 1 retweet 5 likes Reply 1 Retweet 1 Retweeted 1 Like 5 Liked 5 Direct message Omar Rizwan‏ @rsnous Feb 16 More Copy link to Tweet Embed Tweet Mute @rsnous Unmute @rsnous Block @rsnous Unblock @rsnous Report Tweet Add to other Moment Add to new Moment Replying to @rsnous @disquiet07 files are a weak lowest-common-denominator interface between programs in different languages (C, Python, Ruby, Swift, VB, bash, etc) in ecosystems with one language (iOS, JS, Lisp, Smalltalk), you often don't see files: you just persist the rich native structures of the language 4 replies 2 retweets 16 likes Reply 4 Retweet 2 Retweeted 2 Like 16 Liked 16 Direct message Gordon Brander‏ @gordonbrander 3h3 hours ago More Copy link to Tweet Embed Tweet Mute @gordonbrander Unmute @gordonbrander Block @gordonbrander Unblock @gordonbrander Report Tweet Add to other Moment Add to new Moment Replying to @rsnous @disquiet07 OTOH — lowest common denominator interfaces allow for emergent behavior. They focus all the constraints in one place, leaving the rest of the system definition open-ended. Like defining the LEGO dot, but not what shape pieces may take. 1 reply 0 retweets 3 likes Reply 1 Retweet Retweeted Like 3 Liked 3 Direct message Omar Rizwan‏ @rsnous 2h2 hours ago More Copy link to Tweet Embed Tweet Mute @rsnous Unmute @rsnous Block @rsnous Unblock @rsnous Report Tweet Add to other Moment Add to new Moment Replying to @gordonbrander @disquiet07 With files, imo the lack of structure 1. forces duplication of functions at the app level (de/serialization, cross-links, …) and 2. prevents coordination for higher-level behavior #1 here seems different from LEGO, but I can't quite articulate it in terms of your analogy 1 reply 0 retweets 2 likes Reply 1 Retweet Retweeted Like 2 Liked 2 Direct message Gordon Brander‏ @gordonbrander 2h2 hours ago Follow Follow @gordonbrander Following Following @gordonbrander Unfollow Unfollow @gordonbrander Blocked Blocked @gordonbrander Unblock Unblock @gordonbrander Pending Pending follow request from @gordonbrander Cancel Cancel your follow request to @gordonbrander More Copy link to Tweet Embed Tweet Mute @gordonbrander Unmute @gordonbrander Mute this conversation Unmute this conversation Block @gordonbrander Unblock @gordonbrander Report Tweet Add to other Moment Add to new Moment Replying to @rsnous @disquiet07 I agree. Low-level interop has a high floor, high ceiling. Higher-level interop (like Smalltalk) has lower floors, because deeper system integration. However, that deeper integration often means you end up more entangled with the system’s strengths and weaknesses.
    1. I am a grad student. I sought help for my mental illness last year. I go to one of those 'top 10' universities in the US. Grad life is hard, I do not have a lot of support from my family, and I am socially awkward. As far as coursework and work was concerned, I was struggling to organize my work and time. I used to be a huge fan of services like Trello, RescueTime, Evernote, all those technologies out there for managing and organizing. I used notepad or MS Word for documentation and writing reports. I wrote code in Visual Studio and Anaconda's Spyder (no offense to Anaconda). That's what my friends were doing, but I guess it was not enough for me, because I tend to get very nervous when there is a lot of work, and the smallest things can push me off the edge. I need everything to be organized and neat. I discovered Emacs in May 2018. I was in a terrible place then. I thought I was never going to recover. I was just trying out different text editors to optimize my workflow when I found Emacs. The first thing that completely amazed me was org-mode: agenda, the tree structure, org-babel, everything! Then I started writing all my code in Emacs, for all my coursework and work in machine learning, game development, etc. I learned how to store links to particular lines in huge code files, so that I can access them quickly, and continue work where I had left off. I also journal, I have been journaling for 4 years, that is how I deal with my problems. I have tried many software packages for journaling, and none of them come close to what I can do in Emacs. Now I can also write lisp scripts for doing simple routine processes that would make my workflow much simpler, so that I don't have to worry about small details and concentrate on more important things. I have recovered significantly from my depression. I still feel terrible, but I can handle things with more ease because Emacs reduces a lot of unnecessary cognitive load. I wonder what I would have been if I had decided not to explore Emacs. It's true what they say, any text editor can save your files, only Emacs can save your soul.

      about emacs helping to recover from depression, wow!

    1. Rob Pike has described Plan 9 as "an argument" for simplicity and clarity, while others have described it as "UNIX, only moreso."

      idea of a system as an argument pointed out by: https://twitter.com/rsnous/status/1054631468142493696

    1. TIL this is meant to work in Clojure and ClojureScript. Wow… cool! (keys (filter (comp pos? val) {:a 0, :b 1}))

      filter returns mapentries so not a map yet keys works on that!

    2. "Every person is born with an implicit short position on a stream of food and shelter for the length of their life."

      ?? we're making promises conditional on that supply?

    3. The CTO of @circleci aggregated data on build stability and grouped by language. Clojure is most stable, Swift is flakiest. Super interesting. #GitHubUniversepic.twitter.com/D8VEtVDHt8

      clojure stability is it just cause those langs break in runtime?

    4. But the real issue here is the implicit assertion that "improving beginner experience" and "improving expert powers" are in opposition to each other. This talking point is at least five years old, and has never been substantiated.


    5. 3) de-mangle function names (as C++ does) 4) print the stacktrace in a helpful order so I don't have to scroll up 100 lines to see the error 5) Hide implementation details like invokeStatic 6) Show code lines. Do all that and Clojure stack traces would get 100x better.


    6. What python does would be helpful here: 1) don't show more than one layer of internals. Show the clj.core method, but not the lang.RT methods. 2) implement guards to catch errors at the boundaries of user code instead of in the internals of Clojure <cont>


    1. function coll-of allows a :count key to specify the required number of elements:

      good to know that there is the keyword directive :count

    2. In computer science and logic, a dependent type is a type whose definition depends on a value. A "pair of integers" is a type. A "pair of integers where the second is greater than the first" is a dependent type because of the dependence on the value.

      this is not the most impressive defitnition but it does the job ;) it's more like "relational types" where type definitions include relations between potential values

    3. On the flip side, it can go further than mere types, including emulating dependent types and programming-by-contract.

      spec though it's used at runtime (not compile time)

      • hence: not a replacement for types as such BUT
      • enables dependent types
      • programming by contract
    1. Perhaps part of the confusion - and you say this in a different way in your little memo - is that the C/C++ folks see OO as a liberation from a world that has nothing resembling a first-class functions, while Lisp folks see OO as a prison since it limits their use of functions/objects to the style of (9.). In that case, the only way OO can be defended is in the same manner as any other game or discipline -- by arguing that by giving something up (e.g. the freedom to throw eggs at your neighbor's house) you gain something that you want (assurance that your neighbor won't put you in jail).

      [9] "Sum-of-product-of-function pattern - objects are (in effect) restricted to be functions that take as first argument a distinguished method key argument that is drawn from a finite set of simple names."

    2. Sum-of-product-of-function pattern - objects are (in effect) restricted to be functions that take as first argument a distinguished method key argument that is drawn from a finite set of simple names.

      fwiu: the "finte set of simple names" are all the objects defined in the codebase e.g. in java there are no functions as such just methods attached to classes i.e. "their key argument"

    3. All you can do is send a message (AYCDISAM) = Actors model - there is no direct manipulation of objects, only communication with (or invocation of) them. The presence of fields in Java violates this.

      from what I understand in Java... there are some variables on classes (class instances) that are only acessible through methods and for those the "only send message" paradigm holds but there are also fields which are like attributes in python which you can change directly

    4. Parametric polymorphism - functions and data structures that parameterize over arbitrary values (e.g. list of anything). ML and Lisp both have this. Java doesn't quite because of its non-Object types.

      generics so you've got a "template" collection e.g. Collectoin<animal> and you parametrise it with the Animal type in this example how is that broken by "non-Object types" in java</animal>

    5. Ad hoc polymorphism - functions and data structures with parameters that can take on values of many different types.

      does he mean that list in python is polymorphic because it can be list of integers or string or ... ?

    6. Encapsulation - the ability to syntactically hide the implementation of a type. E.g. in C or Pascal you always know whether something is a struct or an array, but in CLU and Java you can hide the difference.

      is this because:

      • interfaces--contextually identical (because satisfy common set of behaviours)?
      • or being wrapped in objects (thus blurring the difference)?
    1. Following Christopher Strachey,[2] parametric polymorphism may be contrasted with ad hoc polymorphism, in which a single polymorphic function can have a number of distinct and potentially heterogeneous implementations depending on the type of argument(s) to which it is applied. Thus, ad hoc polymorphism can generally only support a limited number of such distinct types, since a separate implementation has to be provided for each type.

      kind of like clojure multimethods but those can dispatch on arbitary function hence arbitrary "property"

    2. In programming languages and type theory, parametric polymorphism is a way to make a language more expressive, while still maintaining full static type-safety. Using parametric polymorphism, a function or a data type can be written generically so that it can handle values identically without depending on their type.[1] Such functions and data types are called generic functions and generic datatypes respectively and form the basis of generic programming.

      so essentially this is just a way to escape the contrains of types--overspecifying the type of argument for e.g. append function

      I guess the behaviour implement cannot really implement on the type of value

    1. Best practices will not automatically spare you from development pain. A unique product will have unique problems, and best practices are not a substitute for careful thought.

      but you can do "contextual/local best practices" e.g. don't use abrreviations in function names other than: <team-wide-whitelist-of-abbr></team-wide-whitelist-of-abbr>

    1. One is the linked list of lines you mention. I believe this is intended to solve a display problem that TECO (the original language in which Emacs was implemented) had solved differently using the "gap" data structure. The fundamental issue was that if you have a buffer represented as a single block of contiguous text, then insertion on a character-by-character basis can be O(n2), each time you insert a character, you have to copy the entire subsequent buffer over one space.

      implementation, performence of text entry

    2. Lisp macros were also useful for the definition of new control structures, as well as new data structures. In ZWEI, we created a new iterative control structure called charmap, which iterates over characters in an interval. Intervals are stored as doubly-linked lists of arrays, and the starting point might be in the middle of one array and the ending point might be in the middle of another array. The code to perform this iteration was not trivial, and someone reading it might easily not understand the function it was performing, even though that function was the conceptually simple one of iterating over characters. So we created a macro called charmap that expands into the double-loop code to iterate over the characters. It is simple and obvious, and is used in many places, greatly reducing the size of the code and making the functionality obvious at a glance.

      use of macros implementing data structures making things more readable!

    3. It became policy to avoid abbreviations in most cases. In ZWEI, we made a list of several words that were used extremely often, and established 'official' abbreviations for them, and always used only those abbreviations. ... Words not on this list were always spelled out in full.

      abbreviations whitelist - good programming practice!

    4. The use of the mouse is still considered experimental. We know of several editors which depend highly on the use of a mouse for input, but we are not convinced that it is better than a keyboard; after more people start using ZWEI, it will be interesting to see how many of them make heavy use of the mouse and how many hardly use it at all.

      mouse considered experimental mouse better than keyboard?

    5. Since ZWEI is written in Lisp and lives in the Lisp environment of the Lisp machine, it is in a very good position to interface closely with other elements of that environment.

      living system interacting with a running lisp machine

    6. ZWEI is display-oriented: the text the user is editing is actually displayed (this is relevant because many editors of the time often showed out-of-date text due to efficiency and bandwidth restrictions, putting the burden on the user to imagine what their text looks like currently).

      bandwith restrictions -> out of date text -> user has to imagine what it currently looks like

    7. Some paragraphs are devoted to what must have been a novel concept at the time for such a system: that the Lisp Machine was a personal system, not time-shared, and this gave rise to features not viable on time-sharing systems, due to the fact that the user was not contending with other users for resources.

      personal computers as novel concept (vs time sharing) and what it enables

    1. (How it works: every time you access a document in Mosaic, the group annotation server [if you're using one] is queried with the URL of the document you're viewing; if any group annotations exist for that document, the group annotation server returns to Mosaic corresponding hyperlinks which are inlined into the document just like personal annotations. So the assumption is that you've got a fast local net and group annotation server host. In the Mosaic Annotate and Audio Annotate window there are option menus that let you select 'Personal' or 'Workgroup' each time you make an annotation; for the latter, Mosaic sends the annotation over a socket to the group annotation server.)

      Marc Andreesen about Mosaic anotations server