Experience with wisp
CC Attribution 2.0 Belgium:
You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal purpose as long as the work is attributed to the author in the manner specified by the author or licensor.
Babenhauserheide, Arne
What changed, what evolved, best practices, usage for a lecture, and why wisp aka SRFI-119 is completed as a language (though not in tooling or documentation).
 Thank you for coming. This talk is not about adding a new language, not like creating the new language from scratch, because, well, I want to get finished with it at some point, so rather this is giving you access to all of the scheme, we are indentation-sensitive formatting. Although it won't be as flowery as the talk by Ricardo, which I like very much, because it's a report. It's a report of the steps toward the one-zero. So actually toward getting this done and completed that I can say I don't think that there will be any changes after today. So the talk is about my experience with Witt. Five years. It's now five years since I started this. And the idea was that I looked at Schema and really liked it, but I got a problem with the parents. And I think that's a problem many people have. Yeah, so let me get started. This here is an example of how Wisp looks. The canonical example I use everywhere because I like it a lot. And I started in 2003. Since 2015, this is specified in the Schema Request for Implementation 119. And it's now at version 0.9.9.1 because I missed adding some e-max files. So short about me. I won't talk about everything which is there. I started programming only in 2006 with Python and used that for six years in the PhD almost exclusively. But in 2013, I started going into Schema because I realized that I'm hitting limits of Python. And I saw that in Schema, I can actually go further into how programming can be and not just into using things other people do or just having to go deep into the compiler. The parents shouldn't worry me because I've been using e-max since about 2008. I've been looking into e-lisp, so it shouldn't hurt me, but it still does. I'm strange. Since 2017, now I'm actually working full-time on Java, so I saw the other side and I'm seeing the other side daily. So I can really appreciate what I can do here. Also, we had this about education here. Last year, I had the chance to give a networking technology and communication class at university. And there I could actually use the language to describe to them how an algorithm works. And they asked me whether it's pseudocode, so I was really happy about that. Yes, the part below, you see? My wife and kids are sadly not here, but if they were, I wouldn't have time, so maybe that's good right now. What is Wisp? The vision of Wisp is really to get a syntax like Python, but with keeping the simplicity and power asian-lisp. The way to do that is to get the outer parenthesis away by just inferring them from indentation, to have inline parenthesis for some added beautification, to do inline-infix math just by shelling out to some work other people did before me, and to survive HTML, which Python sadly does not manage, so I knew that it is important. But let's go back. Why is actually scheme grade? When you look at the readability of scheme, while the parents make many people think that it's hard to read, when you look at it in detail, you see that all the contrast structures are just the most common letters you can use if you omit normal a to z, and you omit the math characters and the numbers. All the rest, this is when you look at the order, just the order in how common they are in normal prose. I actually looked at newspapers and books and so on. So this period, comma, quotes, colon, and so on. This is the order how common the characters are, and these are just the characters used in scheme and list. So when you're looking at that, it is really close to just looking like prose. And also, it is flexible enough that you can program your compiler at runtime. So you can actually build everything without relying on the compiler developer. But I would like to ask you to look at these two quote snippets, the one above and the one below, and then think about what if you showed it to your son or your daughter? What would they perceive as easier to read? And for me, that answer is clear. And this is why I'm doing this, because I think that it's actually easier to read. So in short, there's a kind of elegance for me. Scam provides homo-iconicity, I can never speak that right, which just means that you cannot distinguish between code and data if you just look at the subpart of the code of your program. It can both be the same, can both look the same. And you can use code as data and data as code. And then it uses the most common characters. But the elegance I want to add is that the first and last characters of a line shouldn't just be apparent thesis, because then you lose the strongest identifier of each line to always the same character until you manage to unsee it. So why Wisp? I want the simplicity and elegance of scheme with a readability of Python. And I now show you visually how this is done. I had a longer talk about the details here, so I just show it. This is scheme. And this is already valid Wisp. I go back. You see the parent thesis? They disappear. And the one thing which appears are these periods in the beginning, because Wisp just inverts what scheme does and what Lisp does. It does not mark where you call a function. It marks where you don't. And since where you don't call a function, in the next part, when you want to call a function in the next part, you actually don't need to add more indentation than before. You do not need to finish the period. So you actually minimize the syntax from you need two characters at the beginning at the end to just one at the beginning. And lines which do not start a function call are much less common in scheme. I actually grabbed the Gaill source code and two-thirds of the lines start with the parent thesis. And these two-thirds of the lines now do not need that anymore. So the syntax overhead is cut by about factor four. OK. Next step, you see the parent thesis here. They are OK. But sometimes you want to avoid them, because inside parent thesis, Wisp parsing is disabled. So you can always paste in scheme verbatim, and it will run, because this will just be a run through the scheme reader. So you can remove them, which then makes this look even simpler if you're not used to parent thesis, but that's not the reason why it exists. The reason why it exists is that for constructs like Latwell use, you need three parent thesis after each other. So you need a way to represent this as an empty parent thesis, and after it becomes another one. And this is what the colon on the empty line does. It just says here is an indentation level, add a parent thesis, and check the next line. And the inline parent just comes from that, because when you have syntax and you already take up that space, then you should use it as wide as possible. Next part, I had a colleague who looked at my scheme code and said prefix math. And I realized, yes, this is a problem for many people, and for some, especially smaller mathematical expressions, prefix math is hard to read. So I just activate SRFE 105, that's curly infix. So in Wisp, you can always use this expression. Just curly braces around that, and you have infix math. You can also do it in scheme, by the way, at least in Gaian. Just add this curly infix marker, and then you can use infix math. And finally, there's HTML, it won't go away. So we need something which can survive when you strip away, when you collapse all space into one. And this is here the leading underscore. You can in Wisp always replace leading white space by underscores. You just need to keep one single leading white space, at least in front of your token, because otherwise it cannot distinguish between that. So when you write code like this, and you post it into a forum, someone can always copy it, throw it into the rappel, and it will run. So that's it. That's the basics of, no, actually, that's all of Wisp. The indentation is used to show the outer parenthesis. Leading period is used to say, this does not start a procedure call. The colon provides double parenthesis and inline parenthesis. And infix math and underscores are provided for convenience, because otherwise it's, you know, really hard. There are some things which just, the infix math, that's something where people just say, no, and suddenly they are out. And this way we can avoid that. So that's, now we come to what I actually want to say here. That's the past five years, because I used Wisp for about two-thirds to three-quarter of my hobby projects in the past five years just to see whether it works. And I found two things which should have changed, which should be changed, and which are already changed. That's a literal array. Currently, you can make a literal list by just saying quote and the line afterwards, and it is interpreted as the line is quoted. What was missing is I couldn't do arrays. And Geil only treats an array as property of a function if you actually take a literal array. If you say this is an array, then it doesn't do it. So that was certainly needed to add this. And then there's a trailing period to make the wrapper more convenient. But with these changes, I don't see anything else coming. And this is the changes since 2015. So there wasn't a lot. So I think it's stable. Here's a short overview of the stuff I did that goes from writing Py2Guy that was reproducing all my workflows from Python in Geil. Then implementing advection diffusion, building function parameter estimation. Actually the first part was work. Then there comes game scripting. That was what can I do with Wisp? This is what Christopher presented last time here, which was really great. I looked at it in the stream. And then I built a password generator, which I'm using now. I built a network simulator. All this stuff afterwards is networking. The Hamming code is actually an implementation of a Hamming code for a lecture. And then there's Dryad's wake. This is game scripting again, because a colleague left to a game company and wanted to give him a present of something. He can show all the game scripters, hey, this is how it could look. So the first change is what you see here, the two hashes. That makes a literal array. And with that you can implement doc strings in Geil, which are almost like tests in Geil, doc tests, which are almost like the doc tests in Python with a difference. Then in Python you write them in the string. And if you make line breaks, everything breaks until you figure out that you have to quote them. Now in Wisp, and this actually also works in Geil now in normal scheme, you can just define these doc strings and they are normal code. So you write them like you would write the code for that. No difference between the code, your doc tests and so on, it just works. But for that I needed this extra syntax here. And then in the wrapper, typically in Wisp if you run an expression, you have to type enter three times to have it executed, because it waits for two empty lines to say this block is finished. This is the same in the wrapper and in the file, but end of file also counts. Now in the wrapper you often just want to say, I want to execute this expression. So if you put this period behind that and press enter, then it's executed right away and treated as the block is ended here. You can also use this in code files. Question? Yeah? Yes. And in this case, this just takes it and I think it transforms it with a macro. So I'm not perfectly sure, oh repeating the question. Yes, you asked whether this is the first change which doesn't apply to every S expression language and yes, it does not apply to every S expression language. So this is something which is unfortunate to me, but which I needed to get this working in Guile. For doing this in another scheme, for another language, another S expression language, I would leave that out. Okay. So and this is the game scripting. So what you see here is I'm using actually a procedure for a scene and then this is stolen from Shakespeare. The people who are in there enter because they enter and then the name. This defines a macro for the name and then you can just use the name here and type below that what it does and all of this is implemented in macros. So there's no special syntax in Wisp for that. It's just that you can make a macro which looks at the content of the next line, interprets it as symbols, looks at the names of the symbols, takes a string out of that and then shows it character by character, which is really cool that this is possible in scheme and which is one of the justifications why I think that this is something where we should go. And now I think there's time for a short break here because I've been talking the whole time and I should actually stop talking for 30 seconds. This is how the game looks. Did you make it one second earlier? I don't get it much bigger, sadly. Here it asks you a question, you answer that and this question is what you had in the slide as choose. Yes, it's where I want to go and this is what I want to use for games because there you have the writer in the front seat. The writer can always change things and just call scenes and call actions, which is an inversion from the writer having to wait for a feature coming available by the one who writes the scripting language. And you have all of scheme available here. This here, these are just normal procedure calls. As you can see, if you know scheme, actually there's quasi-quoting around the lines, so this is an executed statement. And the result is actually printed. So this is what I did here. Now we come to the educational part. Last year as I said, I had the chance to use Wisp in a lecture and they implemented hamming code for them to show it to them so they could actually understand it from a working example. And this is how that looked. This is the hamming decoder. This is an 11.7 hamming decoder, so it takes 11 input bits and extracts the seven content bits from that and all the wire corrects up to one bit error. It takes here the bits, the C bits are check bits, the D bits are data bits, and then it just calculates the modulo 2 sum of the first check bit and the associated content data bits, multiplies it with one and then it does the same for the second check bit up to the first fourth. And by adding all these, we find where the bit is flipped. Then it flips the broken bit and just extracts from the fixed bits again only the data bits, though the bits starting with D. Question? I used to reading underscore in the last lecture. Because a language does not only have to survive HTML, it also has to survive minted, which kills your indentation when you have more than eight characters of white space. So this is an unexpected advantage that I could actually do that because otherwise this would be garbled. So not only HTML is white space hostile. I skip this and just go, since I only have five minutes left, I think, and just go into where it helps me in learning. So first part, who among you writes code by hands? Who has, let's ask it differently, who has written code with pen on paper? Okay, who was 4 6? I mean, for university I had to. You had to for you? Okay. Yes, I mean my exams were in paper. Actually horrible. Okay, yes. Where should we just organize and we did the coding? I actually do this to understand complex stuff, for example, the network simulator, I wrote like that in my notebook here. And that's how I really understood what I'm doing. And I think that helps a lot. And you see in the writing, this is pretty natural to write down code like that. Then scheme has a beautiful elegance that let Rik. Okay, so let me check. Okay, I'm leaving out these parts. Some of these are already, already set and jumped forward to one of the things I found with works. Use more inner defines in Wisp than in scheme because the indentation is, because deeper indentation is more nasty than deeper nesting in parenthesis. So this is one thing I found which I do differently. And then always prefer procedures over macros when you can and prefer macros over reader extensions. This is why Wisp doesn't do a lot in reader extension because these are nasty to debug and interact badly with other stuff. So skipping this. And so there's finally the future. I want to explore more possibilities here without changing the language itself. It needs more documentation and better tooling. For example, publishing is really unsolved. This is horrible. And then I would really like to get into Guile at some point. And for you, the next time you get to write pseudocode, it would be really cool if you would try to write it as Wisp. You can execute and talk about it and tell me because that's one of the best things to see when someone uses this. And with that, thank you.
 Thank you for coming.  This talk is not about adding a new language, not like creating the new language from scratch,  because, well, I want to get finished with it at some point, so rather this is giving  you access to all of the scheme, we are indentation-sensitive formatting.  Although it won't be as flowery as the talk by Ricardo, which I like very much, because  it's a report.  It's a report of the steps toward the one-zero.  So actually toward getting this done and completed that I can say I don't think that  there will be any changes after today.  So the talk is about my experience with Witt.  Five years.  It's now five years since I started this.  And the idea was that I looked at Schema and really liked it, but I got a problem with  the parents.  And I think that's a problem many people have.  Yeah, so let me get started.  This here is an example of how Wisp looks.  The canonical example I use everywhere because I like it a lot.  And I started in 2003.  Since 2015, this is specified in the Schema Request for Implementation 119.  And it's now at version 0.9.9.1 because I missed adding some e-max files.  So short about me.  I won't talk about everything which is there.  I started programming only in 2006 with Python and used that for six years in the PhD almost  exclusively.  But in 2013, I started going into Schema because I realized that I'm hitting limits of Python.  And I saw that in Schema, I can actually go further into how programming can be and not  just into using things other people do or just having to go deep into the compiler.  The parents shouldn't worry me because I've been using e-max since about 2008.  I've been looking into e-lisp, so it shouldn't hurt me, but it still does.  I'm strange.  Since 2017, now I'm actually working full-time on Java, so I saw the other side and I'm seeing  the other side daily.  So I can really appreciate what I can do here.  Also, we had this about education here.  Last year, I had the chance to give a networking technology and communication class at university.  And there I could actually use the language to describe to them how an algorithm works.  And they asked me whether it's pseudocode, so I was really happy about that.  Yes, the part below, you see?  My wife and kids are sadly not here, but if they were, I wouldn't have time, so maybe  that's good right now.  What is Wisp?  The vision of Wisp is really to get a syntax like Python, but with keeping the simplicity  and power asian-lisp.  The way to do that is to get the outer parenthesis away by just inferring them from indentation,  to have inline parenthesis for some added beautification, to do inline-infix math just  by shelling out to some work other people did before me, and to survive HTML, which  Python sadly does not manage, so I knew that it is important.  But let's go back.  Why is actually scheme grade?  When you look at the readability of scheme, while the parents make many people think that  it's hard to read, when you look at it in detail, you see that all the contrast structures  are just the most common letters you can use if you omit normal a to z, and you omit the  math characters and the numbers.  All the rest, this is when you look at the order, just the order in how common they are  in normal prose.  I actually looked at newspapers and books and so on.  So this period, comma, quotes, colon, and so on.  This is the order how common the characters are, and these are just the characters used  in scheme and list.  So when you're looking at that, it is really close to just looking like prose.  And also, it is flexible enough that you can program your compiler at runtime.  So you can actually build everything without relying on the compiler developer.  But I would like to ask you to look at these two quote snippets, the one above and the  one below, and then think about what if you showed it to your son or your daughter?  What would they perceive as easier to read?  And for me, that answer is clear.  And this is why I'm doing this, because I think that it's actually easier to read.  So in short, there's a kind of elegance for me.  Scam provides homo-iconicity, I can never speak that right, which just means that you  cannot distinguish between code and data if you just look at the subpart of the code of  your program.  It can both be the same, can both look the same.  And you can use code as data and data as code.  And then it uses the most common characters.  But the elegance I want to add is that the first and last characters of a line shouldn't  just be apparent thesis, because then you lose the strongest identifier of each line  to always the same character until you manage to unsee it.  So why Wisp?  I want the simplicity and elegance of scheme with a readability of Python.  And I now show you visually how this is done.  I had a longer talk about the details here, so I just show it.  This is scheme.  And this is already valid Wisp.  I go back.  You see the parent thesis?  They disappear.  And the one thing which appears are these periods in the beginning, because Wisp just  inverts what scheme does and what Lisp does.  It does not mark where you call a function.  It marks where you don't.  And since where you don't call a function, in the next part, when you want to call a  function in the next part, you actually don't need to add more indentation than before.  You do not need to finish the period.  So you actually minimize the syntax from you need two characters at the beginning at  the end to just one at the beginning.  And lines which do not start a function call are much less common in scheme.  I actually grabbed the Gaill source code and two-thirds of the lines start with the parent  thesis.  And these two-thirds of the lines now do not need that anymore.  So the syntax overhead is cut by about factor four.  OK.  Next step, you see the parent thesis here.  They are OK.  But sometimes you want to avoid them, because inside parent thesis, Wisp parsing is disabled.  So you can always paste in scheme verbatim, and it will run, because this will just be  a run through the scheme reader.  So you can remove them, which then makes this look even simpler if you're not used to parent  thesis, but that's not the reason why it exists.  The reason why it exists is that for constructs like Latwell use, you need three parent thesis  after each other.  So you need a way to represent this as an empty parent thesis, and after it becomes another  one.  And this is what the colon on the empty line does.  It just says here is an indentation level, add a parent thesis, and check the next line.  And the inline parent just comes from that, because when you have syntax and you already  take up that space, then you should use it as wide as possible.  Next part, I had a colleague who looked at my scheme code and said prefix math.  And I realized, yes, this is a problem for many people, and for some, especially smaller  mathematical expressions, prefix math is hard to read.  So I just activate SRFE 105, that's curly infix.  So in Wisp, you can always use this expression.  Just curly braces around that, and you have infix math.  You can also do it in scheme, by the way, at least in Gaian.  Just add this curly infix marker, and then you can use infix math.  And finally, there's HTML, it won't go away.  So we need something which can survive when you strip away, when you collapse all space  into one.  And this is here the leading underscore.  You can in Wisp always replace leading white space by underscores.  You just need to keep one single leading white space, at least in front of your token, because  otherwise it cannot distinguish between that.  So when you write code like this, and you post it into a forum, someone can always copy  it, throw it into the rappel, and it will run.  So that's it.  That's the basics of, no, actually, that's all of Wisp.  The indentation is used to show the outer parenthesis.  Leading period is used to say, this does not start a procedure call.  The colon provides double parenthesis and inline parenthesis.  And infix math and underscores are provided for convenience, because otherwise it's, you  know, really hard.  There are some things which just, the infix math, that's something where people just say,  no, and suddenly they are out.  And this way we can avoid that.  So that's, now we come to what I actually want to say here.  That's the past five years, because I used Wisp for about two-thirds to three-quarter  of my hobby projects in the past five years just to see whether it works.  And I found two things which should have changed, which should be changed, and which are already  changed.  That's a literal array.  Currently, you can make a literal list by just saying quote and the line afterwards,  and it is interpreted as the line is quoted.  What was missing is I couldn't do arrays.  And Geil only treats an array as property of a function if you actually take a literal  array.  If you say this is an array, then it doesn't do it.  So that was certainly needed to add this.  And then there's a trailing period to make the wrapper more convenient.  But with these changes, I don't see anything else coming.  And this is the changes since 2015.  So there wasn't a lot.  So I think it's stable.  Here's a short overview of the stuff I did that goes from writing Py2Guy that was reproducing  all my workflows from Python in Geil.  Then implementing advection diffusion, building function parameter estimation.  Actually the first part was work.  Then there comes game scripting.  That was what can I do with Wisp?  This is what Christopher presented last time here, which was really great.  I looked at it in the stream.  And then I built a password generator, which I'm using now.  I built a network simulator.  All this stuff afterwards is networking.  The Hamming code is actually an implementation of a Hamming code for a lecture.  And then there's Dryad's wake.  This is game scripting again, because a colleague left to a game company and wanted to give him  a present of something.  He can show all the game scripters, hey, this is how it could look.  So the first change is what you see here, the two hashes.  That makes a literal array.  And with that you can implement doc strings in Geil, which are almost like tests in Geil,  doc tests, which are almost like the doc tests in Python with a difference.  Then in Python you write them in the string.  And if you make line breaks, everything breaks until you figure out that you have to quote  them.  Now in Wisp, and this actually also works in Geil now in normal scheme, you can just  define these doc strings and they are normal code.  So you write them like you would write the code for that.  No difference between the code, your doc tests and so on, it just works.  But for that I needed this extra syntax here.  And then in the wrapper, typically in Wisp if you run an expression, you have to type  enter three times to have it executed, because it waits for two empty lines to say this block  is finished.  This is the same in the wrapper and in the file, but end of file also counts.  Now in the wrapper you often just want to say, I want to execute this expression.  So if you put this period behind that and press enter, then it's executed right away  and treated as the block is ended here.  You can also use this in code files.  Question?  Yeah?  Yes.  And in this case, this just takes it and I think it transforms it with a macro.  So I'm not perfectly sure, oh repeating the question.  Yes, you asked whether this is the first change which doesn't apply to every S expression  language and yes, it does not apply to every S expression language.  So this is something which is unfortunate to me, but which I needed to get this working  in Guile.  For doing this in another scheme, for another language, another S expression language, I  would leave that out.  Okay.  So and this is the game scripting.  So what you see here is I'm using actually a procedure for a scene and then this is stolen  from Shakespeare.  The people who are in there enter because they enter and then the name.  This defines a macro for the name and then you can just use the name here and type below  that what it does and all of this is implemented in macros.  So there's no special syntax in Wisp for that.  It's just that you can make a macro which looks at the content of the next line, interprets  it as symbols, looks at the names of the symbols, takes a string out of that and then shows  it character by character, which is really cool that this is possible in scheme and which  is one of the justifications why I think that this is something where we should go.  And now I think there's time for a short break here because I've been talking the whole  time and I should actually stop talking for 30 seconds.  This is how the game looks.  Did you make it one second earlier?  I don't get it much bigger, sadly.  Here it asks you a question, you answer that and this question is what you had in the slide  as choose.  Yes, it's where I want to go and this is what I want to use for games because there you  have the writer in the front seat.  The writer can always change things and just call scenes and call actions, which is an  inversion from the writer having to wait for a feature coming available by the one who  writes the scripting language.  And you have all of scheme available here.  This here, these are just normal procedure calls.  As you can see, if you know scheme, actually there's quasi-quoting around the lines, so  this is an executed statement.  And the result is actually printed.  So this is what I did here.  Now we come to the educational part.  Last year as I said, I had the chance to use Wisp in a lecture and they implemented hamming  code for them to show it to them so they could actually understand it from a working example.  And this is how that looked.  This is the hamming decoder.  This is an 11.7 hamming decoder, so it takes 11 input bits and extracts the seven content  bits from that and all the wire corrects up to one bit error.  It takes here the bits, the C bits are check bits, the D bits are data bits, and then it  just calculates the modulo 2 sum of the first check bit and the associated content data  bits, multiplies it with one and then it does the same for the second check bit up to the  first fourth.  And by adding all these, we find where the bit is flipped.  Then it flips the broken bit and just extracts from the fixed bits again only the data bits,  though the bits starting with D. Question?  I used to reading underscore in the last lecture.  Because a language does not only have to survive HTML, it also has to survive minted, which  kills your indentation when you have more than eight characters of white space.  So this is an unexpected advantage that I could actually do that because otherwise this  would be garbled.  So not only HTML is white space hostile.  I skip this and just go, since I only have five minutes left, I think, and just go into  where it helps me in learning.  So first part, who among you writes code by hands?  Who has, let's ask it differently, who has written code with pen on paper?  Okay, who was 4 6?  I mean, for university I had to.  You had to for you?  Okay.  Yes, I mean my exams were in paper.  Actually horrible.  Okay, yes.  Where should we just organize and we did the coding?  I actually do this to understand complex stuff, for example, the network simulator, I wrote  like that in my notebook here.  And that's how I really understood what I'm doing.  And I think that helps a lot.  And you see in the writing, this is pretty natural to write down code like that.  Then scheme has a beautiful elegance that let Rik.  Okay, so let me check.  Okay, I'm leaving out these parts.  Some of these are already, already set and jumped forward to one of the things I found  with works.  Use more inner defines in Wisp than in scheme because the indentation is, because deeper  indentation is more nasty than deeper nesting in parenthesis.  So this is one thing I found which I do differently.  And then always prefer procedures over macros when you can and prefer macros over reader  extensions.  This is why Wisp doesn't do a lot in reader extension because these are nasty to debug  and interact badly with other stuff.  So skipping this.  And so there's finally the future.  I want to explore more possibilities here without changing the language itself.  It needs more documentation and better tooling.  For example, publishing is really unsolved.  This is horrible.  And then I would really like to get into Guile at some point.  And for you, the next time you get to write pseudocode, it would be really cool if you  would try to write it as Wisp.  You can execute and talk about it and tell me because that's one of the best things to  see when someone uses this.  And with that, thank you.
Experience_with_wisp_5_years_with_fewer_parens_cI1sltJMVuM_0_155.png Experience_with_wisp_5_years_with_fewer_parens_cI1sltJMVuM_156_1043.png Experience_with_wisp_5_years_with_fewer_parens_cI1sltJMVuM_1044_1127.png Experience_with_wisp_5_years_with_fewer_parens_cI1sltJMVuM_1128_2435.png Experience_with_wisp_5_years_with_fewer_parens_cI1sltJMVuM_2436_4559.png Experience_with_wisp_5_years_with_fewer_parens_cI1sltJMVuM_4560_5099.png Experience_with_wisp_5_years_with_fewer_parens_cI1sltJMVuM_5100_5567.png Experience_with_wisp_5_years_with_fewer_parens_cI1sltJMVuM_5568_6707.png Experience_with_wisp_5_years_with_fewer_parens_cI1sltJMVuM_6708_14147.png Experience_with_wisp_5_years_with_fewer_parens_cI1sltJMVuM_14148_15359.png Experience_with_wisp_5_years_with_fewer_parens_cI1sltJMVuM_15360_15839.png Experience_with_wisp_5_years_with_fewer_parens_cI1sltJMVuM_15840_16019.png Experience_with_wisp_5_years_with_fewer_parens_cI1sltJMVuM_16020_16151.png Experience_with_wisp_5_years_with_fewer_parens_cI1sltJMVuM_16152_20747.png Experience_with_wisp_5_years_with_fewer_parens_cI1sltJMVuM_20748_21347.png Experience_with_wisp_5_years_with_fewer_parens_cI1sltJMVuM_21348_23591.png Experience_with_wisp_5_years_with_fewer_parens_cI1sltJMVuM_23592_24095.png Experience_with_wisp_5_years_with_fewer_parens_cI1sltJMVuM_24096_29135.png Experience_with_wisp_5_years_with_fewer_parens_cI1sltJMVuM_29136_29915.png Experience_with_wisp_5_years_with_fewer_parens_cI1sltJMVuM_29916_31883.png Experience_with_wisp_5_years_with_fewer_parens_cI1sltJMVuM_31884_32279.png Experience_with_wisp_5_years_with_fewer_parens_cI1sltJMVuM_32280_33022.png