<?xml version='1.0' encoding='utf-8' ?>

<rss version='2.0' xmlns:lj='http://www.livejournal.org/rss/lj/1.0/' xmlns:atom10='http://www.w3.org/2005/Atom'>
<channel>
  <title>Snail#</title>
  <link>https://snailsharp.dreamwidth.org/</link>
  <description>Snail# - Dreamwidth Studios</description>
  <lastBuildDate>Sun, 30 Jul 2023 00:54:19 GMT</lastBuildDate>
  <generator>LiveJournal / Dreamwidth Studios</generator>
  <lj:journal>snailsharp</lj:journal>
  <lj:journaltype>community</lj:journaltype>
  <image>
    <url>https://v2.dreamwidth.org/16164916/4065555</url>
    <title>Snail#</title>
    <link>https://snailsharp.dreamwidth.org/</link>
    <width>100</width>
    <height>100</height>
  </image>

<item>
  <guid isPermaLink='true'>https://snailsharp.dreamwidth.org/4013.html</guid>
  <pubDate>Sun, 30 Jul 2023 00:54:19 GMT</pubDate>
  <title>Nice Little Things in Visual Basic .NET</title>
  <link>https://snailsharp.dreamwidth.org/4013.html</link>
  <description>Posted by: &lt;span lj:user=&apos;isaacschemm&apos; style=&apos;white-space: nowrap;&apos; class=&apos;ljuser&apos;&gt;&lt;a href=&apos;https://isaacschemm.dreamwidth.org/profile&apos;&gt;&lt;img src=&apos;https://www.dreamwidth.org/img/silk/identity/user.png&apos; alt=&apos;[personal profile] &apos; width=&apos;17&apos; height=&apos;17&apos; style=&apos;vertical-align: text-bottom; border: 0; padding-right: 1px;&apos; /&gt;&lt;/a&gt;&lt;a href=&apos;https://isaacschemm.dreamwidth.org/&apos;&gt;&lt;b&gt;isaacschemm&lt;/b&gt;&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Being (loosely) based on the original Visual Basic, it&apos;s not surprising that Visual Basic .NET has features specifically targeted towards Windows Forms development. When I want to make a quick GUI app to run on my PC, I often find it easiest to build the main code in a C# or F# library, and to build a thin frontend layer in VB.NET, for two reasons: the incredibly aggressive (in a good way) auto-formatting that keeps me from being distracted by code style, and the nice set of quality-of-life helpers the language gives you for this exact use case.&lt;/p&gt;&lt;span class=&quot;cut-wrapper&quot;&gt;&lt;span style=&quot;display: none;&quot; id=&quot;span-cuttag___1&quot; class=&quot;cuttag&quot;&gt;&lt;/span&gt;&lt;b class=&quot;cut-open&quot;&gt;(&amp;nbsp;&lt;/b&gt;&lt;b class=&quot;cut-text&quot;&gt;&lt;a href=&quot;https://snailsharp.dreamwidth.org/4013.html#cutid1&quot;&gt;Read more...&lt;/a&gt;&lt;/b&gt;&lt;b class=&quot;cut-close&quot;&gt;&amp;nbsp;)&lt;/b&gt;&lt;/span&gt;&lt;div style=&quot;display: none;&quot; id=&quot;div-cuttag___1&quot; aria-live=&quot;assertive&quot;&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src=&quot;https://www.dreamwidth.org/tools/commentcount?user=snailsharp&amp;ditemid=4013&quot; width=&quot;30&quot; height=&quot;12&quot; alt=&quot;comment count unavailable&quot; style=&quot;vertical-align: middle;&quot;/&gt; comments</description>
  <comments>https://snailsharp.dreamwidth.org/4013.html</comments>
  <category>windows</category>
  <category>dotnet</category>
  <category>visualbasic</category>
  <lj:security>public</lj:security>
  <lj:poster>isaacschemm</lj:poster>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>https://snailsharp.dreamwidth.org/3568.html</guid>
  <pubDate>Thu, 20 Apr 2023 17:57:23 GMT</pubDate>
  <title>Breaking podcasts into chunks for burning to CD</title>
  <link>https://snailsharp.dreamwidth.org/3568.html</link>
  <description>Posted by: &lt;span lj:user=&apos;isaacschemm&apos; style=&apos;white-space: nowrap;&apos; class=&apos;ljuser&apos;&gt;&lt;a href=&apos;https://isaacschemm.dreamwidth.org/profile&apos;&gt;&lt;img src=&apos;https://www.dreamwidth.org/img/silk/identity/user.png&apos; alt=&apos;[personal profile] &apos; width=&apos;17&apos; height=&apos;17&apos; style=&apos;vertical-align: text-bottom; border: 0; padding-right: 1px;&apos; /&gt;&lt;/a&gt;&lt;a href=&apos;https://isaacschemm.dreamwidth.org/&apos;&gt;&lt;b&gt;isaacschemm&lt;/b&gt;&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Sometimes I want to listen to a podcast on a TV, and sometimes
the easiest way to do that is by burning it to a CD (either a
CD-ROM with MP3 files, or - if it fits - a normal audio CD). Not
every CD player has the greatest seeking features, though. I&apos;ve
got one whose fast-forward is more of a normal-speed-forward, and
another that actually goes &lt;i&gt;forward &lt;/i&gt;when rewinding an MP3
at the slowest level.&lt;br&gt;
&lt;/p&gt;
&lt;p&gt;I figured one way of working around these issues - which could
come into play for podcast episodes that are, like, an hour long -
would be to split the podcast into segments of five minutes each.
You&apos;d need to make a normal audio CD (which means a limit of 75 or
80 minutes or so), but you could have gapless playback, while also
being able to use track selection to go forward and back in
chunks.&lt;br&gt;
&lt;/p&gt;
&lt;p&gt;Yesterday I put together a small Windows application to help with
this. It&apos;s called &lt;a moz-do-not-send=&quot;true&quot; href=&quot;https://github.com/IsaacSchemm/CueSheetGenerator/releases&quot;&gt;Cue
Sheet Generator&lt;/a&gt;, and it takes in one or more audio files and
converts them to either a set of .wav files (to burn with Windows
Media Player Legacy or another app with gapless burning support)
or a .wav/.cue pair (which ImgBurn and other such apps can
handle).&lt;br&gt;
&lt;/p&gt;
&lt;p&gt;The main program logic is small enough to fit into this post. I
wrote it in VB.NET (there&apos;s nothing here C# couldn&apos;t do, I&apos;m just
tired of looking at curly brackets), and I thought it might be
helpful to annotate it.&lt;br&gt;
&lt;/p&gt;
&lt;span class=&quot;cut-wrapper&quot;&gt;&lt;span style=&quot;display: none;&quot; id=&quot;span-cuttag___1&quot; class=&quot;cuttag&quot;&gt;&lt;/span&gt;&lt;b class=&quot;cut-open&quot;&gt;(&amp;nbsp;&lt;/b&gt;&lt;b class=&quot;cut-text&quot;&gt;&lt;a href=&quot;https://snailsharp.dreamwidth.org/3568.html#cutid1&quot;&gt;Read more...&lt;/a&gt;&lt;/b&gt;&lt;b class=&quot;cut-close&quot;&gt;&amp;nbsp;)&lt;/b&gt;&lt;/span&gt;&lt;div style=&quot;display: none;&quot; id=&quot;div-cuttag___1&quot; aria-live=&quot;assertive&quot;&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src=&quot;https://www.dreamwidth.org/tools/commentcount?user=snailsharp&amp;ditemid=3568&quot; width=&quot;30&quot; height=&quot;12&quot; alt=&quot;comment count unavailable&quot; style=&quot;vertical-align: middle;&quot;/&gt; comments</description>
  <comments>https://snailsharp.dreamwidth.org/3568.html</comments>
  <category>audio</category>
  <category>visualbasic</category>
  <category>cd</category>
  <lj:security>public</lj:security>
  <lj:poster>isaacschemm</lj:poster>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>https://snailsharp.dreamwidth.org/2660.html</guid>
  <pubDate>Wed, 15 Mar 2023 18:23:15 GMT</pubDate>
  <title>Give me a yield break</title>
  <link>https://snailsharp.dreamwidth.org/2660.html</link>
  <description>Posted by: &lt;span lj:user=&apos;isaacschemm&apos; style=&apos;white-space: nowrap;&apos; class=&apos;ljuser&apos;&gt;&lt;a href=&apos;https://isaacschemm.dreamwidth.org/profile&apos;&gt;&lt;img src=&apos;https://www.dreamwidth.org/img/silk/identity/user.png&apos; alt=&apos;[personal profile] &apos; width=&apos;17&apos; height=&apos;17&apos; style=&apos;vertical-align: text-bottom; border: 0; padding-right: 1px;&apos; /&gt;&lt;/a&gt;&lt;a href=&apos;https://isaacschemm.dreamwidth.org/&apos;&gt;&lt;b&gt;isaacschemm&lt;/b&gt;&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Working in .NET, I&apos;ve been in a situation where I need to implement a function in an interface that&apos;s supposed to return an IEnumerable&amp;lt;T&amp;gt;. (In some cases, I&apos;d argue that IReadOnlyList&amp;lt;T&amp;gt; might make more sense - this way, the caller knows it&apos;s not going to be a lazily-evaluated sequence, and you can still return a .NET&amp;nbsp;list, F# list, or array - but I digress).&lt;/p&gt; &lt;p&gt;Maybe the most obvious way to do this is by calling a function that explicitly returns an empty enumerable for you:&lt;/p&gt; &lt;pre&gt;
IEnumerable&amp;lt;string&amp;gt; SampleInterface.getAll() =&amp;gt; Enumerable.Empty&amp;lt;string&amp;gt;();&lt;/pre&gt;  &lt;p&gt;In F#, it would be even shorter, because of the aggressive type resolution:&lt;/p&gt; &lt;pre&gt;
interface SampleInterface with
    member _.getAll() = Seq.empty&lt;/pre&gt; &lt;p&gt;There are other clever ways to do the same thing, though, and it might just depend on what you think is the clearest or most readable - which might just mean keeping it consistent with the code around it. First, you can always expand out the function (because clearer isn&apos;t always shorter - I think it really does depend on the context of what&apos;s around it):&lt;/p&gt; &lt;pre&gt;
IEnumerable&amp;lt;string&amp;gt; SampleInterface.getAll() {
    return Enumerable.Empty&amp;lt;string&amp;gt;();
}&lt;/pre&gt; &lt;p&gt;But there&apos;s also something clever you can do here, if you want to &lt;em&gt;think&lt;/em&gt; of your code in a different way - where instead of resulting in &amp;quot;an empty list&amp;quot;, it results in &amp;quot;no elements&amp;quot;. C# lets you build iterator functions, where your code defines an IEnumerable&amp;lt;T&amp;gt; (and runs every time the resulting object is enumerated). Any function with a &lt;code&gt;yield return&lt;/code&gt; or a &lt;code&gt;yield break&lt;/code&gt; is treated in this way by the compiler. This means you can implement a function that returns &amp;quot;no elements&amp;quot; just by doing this:&lt;/p&gt; &lt;pre&gt;
IEnumerable&amp;lt;string&amp;gt; SampleInterface.getAll() {
    yield break;
}&lt;/pre&gt; &lt;p&gt;It&apos;s a bit different in VB.NET, where iterator functions are denoted explicitly - so the yield break isn&apos;t needed:&lt;/p&gt; &lt;pre&gt;
Public Iterator Function getAll() As IEnumerable(Of String) Implements SampleInterface.getAll

End Function&lt;/pre&gt; &lt;p&gt;That is, in a very literal sense, a function that returns no elements!&lt;/p&gt; &lt;p&gt;Funny thing is that there&apos;s no real equivalent to an empty iterator function in F# (not that you&apos;d need it); the compiler won&apos;t allow a &lt;code&gt;seq { }&lt;/code&gt; workflow without any elements in it, and suggests you use &lt;code&gt;Seq.empty&lt;/code&gt; or the empty list &lt;code&gt;[]&lt;/code&gt; instead.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src=&quot;https://www.dreamwidth.org/tools/commentcount?user=snailsharp&amp;ditemid=2660&quot; width=&quot;30&quot; height=&quot;12&quot; alt=&quot;comment count unavailable&quot; style=&quot;vertical-align: middle;&quot;/&gt; comments</description>
  <comments>https://snailsharp.dreamwidth.org/2660.html</comments>
  <category>dotnet</category>
  <category>visualbasic</category>
  <category>csharp</category>
  <lj:security>public</lj:security>
  <lj:poster>isaacschemm</lj:poster>
  <lj:reply-count>0</lj:reply-count>
</item>
</channel>
</rss>
