<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-32637828</id><updated>2026-02-10T20:32:23.881+00:00</updated><category term="programming"/><category term="Java"/><category term="UNIX"/><category term="bash"/><category term="commands"/><category term="scripting"/><category term="java8"/><category term="interview"/><category term="eclipse"/><category term="streams"/><category term="java7"/><category term="profile"/><category term="shell"/><category term="Linux"/><category term="Windows"/><category term="stackoverflow"/><category term="testing"/><category term="XML"/><category term="javascript"/><category term="kdb"/><category term="q"/><category term="software"/><category term="html"/><category term="html5"/><category term="junit"/><category term="spring"/><category term="concurrency"/><category term="tips"/><category term="Microsoft"/><category term="algorithm"/><category term="csv"/><category term="java9"/><category term="memory"/><category term="extjs"/><category term="google"/><category term="performance"/><category term="utilities"/><category term="Oracle"/><category term="SSH"/><category term="database"/><category term="exceptions"/><category term="firefox"/><category term="guava"/><category term="javaconfig"/><category term="jsfiddle"/><category term="maven"/><category term="python"/><category term="solaris"/><category term="sybase"/><category term="system"/><category term="Ubuntu"/><category term="XP"/><category term="XSLT"/><category term="animal testing"/><category term="completion"/><category term="coursera"/><category term="cpu"/><category term="download"/><category term="e-learning"/><category term="favicon"/><category term="firefox3"/><category term="ganymede"/><category term="hibernate"/><category term="holiday"/><category term="java10"/><category term="java11"/><category term="java14"/><category term="java16"/><category term="java19"/><category term="java21"/><category term="java22"/><category term="java24"/><category term="jdbc"/><category term="json"/><category term="junit5"/><category term="lambdas"/><category term="mocking"/><category term="optional"/><category term="scala"/><category term="singapore"/><category term="swing"/><category term="syntaxhighlighter"/><category term="vimrc"/><category term="web"/><category term="webdesign"/><category term="xpath"/><category term="GC"/><category term="JMS"/><category term="Javadoc"/><category term="RMI"/><category term="alias"/><category term="awk"/><category term="bit-shifting"/><category term="browser"/><category term="canvas"/><category term="certificate"/><category term="computer"/><category term="core-dump"/><category term="crontab"/><category term="css"/><category term="debug"/><category term="email"/><category term="epoch"/><category term="essay"/><category term="excel"/><category term="factorial"/><category term="ffmpeg"/><category term="fork-join"/><category term="game"/><category term="garbage collection"/><category term="git"/><category term="hardware"/><category term="java12"/><category term="java13"/><category term="java25"/><category term="jaxb"/><category term="jconsole"/><category term="joins"/><category term="jol"/><category term="log4j"/><category term="logging"/><category term="mockito"/><category term="outlook"/><category term="perl"/><category term="pictures"/><category term="pidgin"/><category term="pmc"/><category term="pro/con"/><category term="progress"/><category term="resultset"/><category term="searchplugin"/><category term="shirt"/><category term="shutdownhook"/><category term="spoj"/><category term="sql"/><category term="templates"/><category term="tmux"/><category term="version"/><category term="web workers"/><category term="xmllint"/><category term="&quot;eid in the square&quot;"/><category term="&quot;google chart api&quot;"/><category term="&quot;vertical rush&quot;"/><category term="&quot;vertical rush&quot; stairs climb"/><category term="2007"/><category term="Apple"/><category term="CVS"/><category term="CollabNet"/><category term="IFS"/><category term="Islam"/><category term="Kawashima"/><category term="LRO"/><category term="NASA"/><category term="OPML"/><category term="PS2"/><category term="SMTPAppender"/><category term="SSL"/><category term="Vista"/><category term="Windows MSN Messenger 7.5 software tips tweaks hack"/><category term="addon"/><category term="adventofcode"/><category term="age"/><category term="alert"/><category term="android"/><category term="ant"/><category term="aol"/><category term="args4j"/><category term="associative arrays"/><category term="autosys"/><category term="bcp"/><category term="bios"/><category term="blob"/><category term="bonus"/><category term="bookmarklet"/><category term="brain training"/><category term="broadband"/><category term="btrace"/><category term="bug"/><category term="caching"/><category term="charts"/><category term="cinema imax films"/><category term="climb"/><category term="clob"/><category term="cobertura"/><category term="code"/><category term="commons-cli"/><category term="commons-config"/><category term="compile"/><category term="completablefuture"/><category term="compression"/><category term="connection"/><category term="console"/><category term="date"/><category term="datetime"/><category term="deadlock"/><category term="default methods"/><category term="delete"/><category term="dell"/><category term="design patterns"/><category term="document"/><category term="eid"/><category term="error"/><category term="extrovert"/><category term="facebook"/><category term="feeds"/><category term="fibonacci"/><category term="file"/><category term="files"/><category term="find"/><category term="food"/><category term="fork-bomb"/><category term="fuser"/><category term="gdb"/><category term="getopt"/><category term="getopts"/><category term="glibc"/><category term="globbing"/><category term="graphs"/><category term="grc"/><category term="grep"/><category term="hamcrest"/><category term="hampton court"/><category term="hashmap"/><category term="hermes"/><category term="highlighting"/><category term="house"/><category term="howto"/><category term="hsqldb"/><category term="httpclient"/><category term="humour"/><category term="infinity"/><category term="install"/><category term="intern"/><category term="internet"/><category term="introvert"/><category term="isobuster"/><category term="isql"/><category term="java15"/><category term="java17"/><category term="java18"/><category term="java20"/><category term="jcommander"/><category term="jdk7"/><category term="jmeter"/><category term="jmx"/><category term="join"/><category term="jquery"/><category term="jshell"/><category term="juno"/><category term="jwebserver"/><category term="jxls"/><category term="keytool"/><category term="kill"/><category term="laptop"/><category term="life"/><category term="logback"/><category term="macro"/><category term="map"/><category term="mathml"/><category term="mbeans"/><category term="md5"/><category term="moon"/><category term="mount"/><category term="moving"/><category term="multiplication"/><category term="multitail"/><category term="network"/><category term="nintendo ds"/><category term="null"/><category term="ocs"/><category term="open source"/><category term="organise"/><category term="parallelarray"/><category term="permgen"/><category term="personality"/><category term="photos"/><category term="picitup"/><category term="plugin"/><category term="process"/><category term="profiling"/><category term="promotion"/><category term="property"/><category term="quartz"/><category term="questions"/><category term="rare award"/><category term="react"/><category term="read"/><category term="reader"/><category term="record"/><category term="recover"/><category term="regex"/><category term="regression"/><category term="relational algebra"/><category term="release"/><category term="restoration"/><category term="restore"/><category term="review"/><category term="rss"/><category term="samba"/><category term="scribd"/><category term="search"/><category term="security"/><category term="sed"/><category term="serialization"/><category term="sharing"/><category term="shutdown"/><category term="skip"/><category term="social"/><category term="space travel"/><category term="sqlite"/><category term="sqlplus"/><category term="sqsh"/><category term="sso"/><category term="stairs"/><category term="stanford"/><category term="statistics"/><category term="studio"/><category term="technology"/><category term="trafalgar"/><category term="trip"/><category term="tweaks"/><category term="twitter"/><category term="uname"/><category term="uptime"/><category term="var"/><category term="vim"/><category term="vivisection"/><category term="vtd-xml"/><category term="waol.exe"/><category term="weblogic"/><category term="whitespace"/><category term="windows 10"/><category term="work"/><category term="wrapper"/><category term="wsl"/><category term="xstream"/><title type='text'>fahd.blog</title><subtitle type='html'>Let the code do the talking...</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://fahdshariff.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/32637828/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://fahdshariff.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/32637828/posts/default?start-index=26&amp;max-results=25&amp;redirect=false'/><author><name>Fahd Shariff</name><uri>http://www.blogger.com/profile/00919911016127601294</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyUY9JyEBDYzkRuo6ZcCIH40ft7Uo0CcAZL_NMxtyWnKW76BmrZwDbduRP2c8taq9QAgjlVCFPvCD0Vhxbt6_xAEwolBSnviy6wI_XO00TV8trJNKlpM-HtAB4RvQf_0M/s220/mvbSKNwL.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>428</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-32637828.post-3781135293544169505</id><published>2026-01-01T15:49:00.000+00:00</published><updated>2026-01-01T15:49:07.849+00:00</updated><title type='text'>fahd.blog in 2025</title><content type='html'>&lt;p&gt;&lt;b&gt;&lt;font color=&quot;#000099&quot;&gt;Happy 2026, everyone!&lt;/font&gt;&lt;/b&gt;&lt;/p&gt;&lt;p&gt;I&#39;d like to wish everyone a great start to an even greater new year!&lt;/p&gt;

&lt;p&gt;In keeping with tradition, here&#39;s one last look back at &lt;a href=&quot;http://fahdshariff.blogspot.com&quot;&gt;fahd.blog&lt;/a&gt; in 2025.&lt;/p&gt;

&lt;p&gt;During 2025, I posted 8 new entries on &lt;a href=&quot;http://fahdshariff.blogspot.com&quot;&gt;fahd.blog&lt;/a&gt;. I am also thrilled that I have more readers from all over the world! Thanks for reading and especially for giving feedback.&lt;/p&gt;

&lt;b&gt;&lt;font color=&quot;#000099&quot;&gt;Top 3 posts of 2025:&lt;/font&gt;&lt;/b&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://fahdshariff.blogspot.com/2025/05/java-24-structured-concurrency.html&quot;&gt;Java 24: Structured Concurrency&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://fahdshariff.blogspot.com/2025/03/java-24-scoped-values.html&quot;&gt;Java 24: Scoped Values&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://fahdshariff.blogspot.com/2025/03/java-24-primitive-types-in-patterns.html&quot;&gt;Java 24: Primitive Types in Patterns, instanceof, and switch&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I&#39;m going to be writing a lot more this year, so stay tuned for more great techie tips, tricks and hacks! :)&lt;/p&gt;

&lt;b&gt;&lt;font color=&quot;#000099&quot;&gt;Related posts:&lt;/font&gt;&lt;/b&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://fahdshariff.blogspot.com/2025/01/fahdblog-in-2024.html&quot;&gt;fahd.blog in 2024&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://fahdshariff.blogspot.com/2024/01/fahdblog-in-2023.html&quot;&gt;fahd.blog in 2023&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://fahdshariff.blogspot.com/2023/01/fahdblog-in-2022.html&quot;&gt;fahd.blog in 2022&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://fahdshariff.blogspot.com/2022/01/fahdblog-in-2021.html&quot;&gt;fahd.blog in 2021&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://fahdshariff.blogspot.com/2021/01/fahdblog-in-2020.html&quot;&gt;fahd.blog in 2020&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://fahdshariff.blogspot.com/2020/01/fahdblog-in-2019.html&quot;&gt;fahd.blog in 2019&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://fahdshariff.blogspot.com/2019/01/fahdblog-in-2018.html&quot;&gt;fahd.blog in 2018&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://fahdshariff.blogspot.com/2018/01/fahdblog-in-2017.html&quot;&gt;fahd.blog in 2017&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://fahdshariff.blogspot.com/2017/01/fahdblog-in-2016.html&quot;&gt;fahd.blog in 2016&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://fahdshariff.blogspot.com/2016/01/fahdblog-in-2015.html&quot;&gt;fahd.blog in 2015&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://fahdshariff.blogspot.com/2015/01/fahdblog-in-2014.html&quot;&gt;fahd.blog in 2014&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://fahdshariff.blogspot.com/2014/01/fahdblog-in-2013.html&quot;&gt;fahd.blog in 2013&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><link rel='replies' type='application/atom+xml' href='http://fahdshariff.blogspot.com/feeds/3781135293544169505/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fahdshariff.blogspot.com/2026/01/fahdblog-in-2025.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/32637828/posts/default/3781135293544169505'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/32637828/posts/default/3781135293544169505'/><link rel='alternate' type='text/html' href='http://fahdshariff.blogspot.com/2026/01/fahdblog-in-2025.html' title='fahd.blog in 2025'/><author><name>Fahd Shariff</name><uri>http://www.blogger.com/profile/00919911016127601294</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyUY9JyEBDYzkRuo6ZcCIH40ft7Uo0CcAZL_NMxtyWnKW76BmrZwDbduRP2c8taq9QAgjlVCFPvCD0Vhxbt6_xAEwolBSnviy6wI_XO00TV8trJNKlpM-HtAB4RvQf_0M/s220/mvbSKNwL.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-32637828.post-496405752112227510</id><published>2025-12-26T08:00:00.003+00:00</published><updated>2025-12-26T08:00:00.117+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Java"/><category scheme="http://www.blogger.com/atom/ns#" term="java25"/><category scheme="http://www.blogger.com/atom/ns#" term="programming"/><title type='text'>Java 25: Stable Values</title><content type='html'>
&lt;p&gt;&lt;a href=&quot;https://www.oracle.com/uk/java/technologies/javase/25-relnote-issues.html&quot;&gt;Java 25&lt;/a&gt; introduces &lt;a href=&quot;https://openjdk.org/jeps/502&quot;&gt;Stable Values&lt;/a&gt;, which are objects that hold immutable data. They let you initialise immutable fields lazily, while still allowing the JVM to treat them as constants, and thus perform the same optimisations (such as constant-folding) that are done for &lt;code&gt;final&lt;/code&gt; fields. This is a &lt;a href=&quot;https://openjdk.org/jeps/487&quot;&gt;preview language feature&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Consider the following example:&lt;/p&gt;

&lt;pre class=&quot;brush:java; gutter:false;&quot;&gt;
public class Controller {
    private final ExpensiveResource resource = new ExpensiveResource();
    
    public void process(String request) {
        resource.get(request);
    }
}
&lt;/pre&gt;

&lt;p&gt;The problem here is that, since &lt;code&gt;resource&lt;/code&gt; is a &lt;code&gt;final&lt;/code&gt; field, it must be initialised eagerly, which means creating a &lt;code&gt;Controller&lt;/code&gt; can be slow. It&#39;s also unnecessary to create the expensive resource if the &lt;code&gt;process&lt;/code&gt; method is never called during the runtime of the application. In order to &quot;defer immutability&quot; and lazily initialise fields, we have to use complex workarounds such as the &lt;a href=&quot;https://en.wikipedia.org/wiki/Initialization-on-demand_holder_idiom&quot;&gt;class-holder idiom&lt;/a&gt;, as shown below:&lt;/p&gt;

&lt;pre class=&quot;brush:java; gutter:false;&quot;&gt;
public class Controller {
    public static ExpensiveResource getResource() {
        class Holder {
            private static final ExpensiveResource RESOURCE =
                    new ExpensiveResource();
        }
        return Holder.RESOURCE;
    }

    public void process(String request) {
        getResource().get(request);
    }
}
&lt;/pre&gt;


&lt;p&gt;This is where &lt;b&gt;Stable Values&lt;/b&gt; come in.&lt;/p&gt;

&lt;p&gt;Here is the same class, rewritten using a &lt;a href=&quot;https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/lang/StableValue.html&quot;&gt;&lt;code&gt;StableVaue&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;

&lt;pre class=&quot;brush:java; gutter:false;&quot;&gt;
public class Controller {
    private final StableValue&amp;lt;ExpensiveResource&amp;gt; resource = StableValue.of();

    public ExpensiveResource getResource() {
        return resource.orElseSet(() -&amp;gt; new ExpensiveResource());
    }

    public void process(String request) {
        getResource().get(request);
    }
}
&lt;/pre&gt;
&lt;p&gt;Initially, the stable value holds no content. When the &lt;code&gt;orElseSet&lt;/code&gt; method is invoked for the first time, the expensive resource is initialised and set into the stable value, and subsequent calls will simply return it. The &lt;code&gt;orElseSet&lt;/code&gt; method guarantees that the provided lambda expression is evaluated only once, even when it is invoked concurrently.&lt;/p&gt;

&lt;p&gt;A more convenient way to use stable values is via a &lt;code&gt;Supplier&lt;/code&gt; instead, as shown below:&lt;/p&gt;

&lt;pre class=&quot;brush:java; gutter:false;&quot;&gt;
public class Controller {
    private final Supplier&amp;lt;ExpensiveResource&amp;gt; resource = 
        StableValue.supplier(() -&amp;gt; new ExpensiveResource());

    public void process(String request) {
        resource.get().get(request);
    }
}
&lt;/pre&gt;
&lt;p&gt;Using a stable value supplier, rather than a stable value, is more readable because the declaration and initialisation of the &lt;code&gt;resource&lt;/code&gt; field are now together.&lt;/p&gt;

&lt;p&gt;Under the hood, a stable value is a non-final field annotated with the JDK-internal &lt;code&gt;@Stable&lt;/code&gt; annotation. This tells the JVM that the field will never change after it is written. Due to this guarantee, the JVM can treat the value like a constant, provided that the reference to the stable value is &lt;code&gt;final&lt;/code&gt;, and perform constant-folding optimisations, even through multiple layers of stable values.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://fahdshariff.blogspot.com/feeds/496405752112227510/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fahdshariff.blogspot.com/2025/12/java-25-stable-values.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/32637828/posts/default/496405752112227510'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/32637828/posts/default/496405752112227510'/><link rel='alternate' type='text/html' href='http://fahdshariff.blogspot.com/2025/12/java-25-stable-values.html' title='Java 25: Stable Values'/><author><name>Fahd Shariff</name><uri>http://www.blogger.com/profile/00919911016127601294</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyUY9JyEBDYzkRuo6ZcCIH40ft7Uo0CcAZL_NMxtyWnKW76BmrZwDbduRP2c8taq9QAgjlVCFPvCD0Vhxbt6_xAEwolBSnviy6wI_XO00TV8trJNKlpM-HtAB4RvQf_0M/s220/mvbSKNwL.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-32637828.post-2308513057814910556</id><published>2025-12-22T08:00:00.001+00:00</published><updated>2025-12-22T08:00:00.134+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Java"/><category scheme="http://www.blogger.com/atom/ns#" term="java25"/><category scheme="http://www.blogger.com/atom/ns#" term="jol"/><category scheme="http://www.blogger.com/atom/ns#" term="memory"/><category scheme="http://www.blogger.com/atom/ns#" term="programming"/><title type='text'>Java 25: Compact Object Headers</title><content type='html'>
&lt;p&gt;&lt;a href=&quot;https://www.oracle.com/uk/java/technologies/javase/25-relnote-issues.html&quot;&gt;Java 25&lt;/a&gt; introduces &lt;a href=&quot;https://openjdk.org/jeps/519&quot;&gt;Compact Object Headers&lt;/a&gt;, an optimisation that reduces the memory overhead of Java objects.&lt;/p&gt;

&lt;p&gt;In my &lt;a href=&quot;https://fahdshariff.blogspot.com/2025/12/measuring-java-object-size-with-jol.html&quot;&gt;previous post&lt;/a&gt;, I wrote about how you can measure the size of java objects using JOL, and inspect the size of the object header. For example, take the following class:&lt;/p&gt;

&lt;pre class=&quot;brush:java; gutter:false;&quot;&gt;
public class Point {
  int x;
  int y;
}
&lt;/pre&gt;

&lt;p&gt;Use JOL to inspect its layout:&lt;/p&gt;
&lt;pre class=&quot;brush:java; gutter:false;&quot;&gt;
import org.openjdk.jol.info.ClassLayout;

public class JolExample {
  public static void main(String[] args) {
    System.out.println(ClassLayout.parseClass(Point.class).toPrintable());
  }
}
&lt;/pre&gt;

&lt;p&gt;The output is:&lt;/p&gt;
&lt;pre style=&quot;font-family: Consolas,Courier New,Courier,mono,serif; font-size:12px;&quot;&gt;
Point object internals:
OFF  SZ   TYPE DESCRIPTION               VALUE
  0   8        (object header: mark)     N/A
  8   4        (object header: class)    N/A
 12   4    int Point.x                   N/A
 16   4    int Point.y                   N/A
 20   4        (object alignment gap)    
Instance size: 24 bytes
&lt;/pre&gt;

&lt;p&gt;This shows that even though the &lt;code&gt;Point&lt;/code&gt; class only has 2 int fields requiring a total of 8 bytes, the actual object uses three times that amount (24 bytes), due to the object header (12 bytes) and alignment (4 bytes).&lt;/p&gt;

&lt;p&gt;Now let&#39;s turn on Compact Object Headers using the following JVM flag:&lt;/p&gt;
&lt;pre style=&quot;font-family: Consolas,Courier New,Courier,mono,serif; font-size:16px;&quot;&gt;&lt;b&gt;-XX:+UseCompactObjectHeaders&lt;/b&gt;&lt;/pre&gt;

&lt;p&gt;Rerunning JOL, outputs the following:&lt;/p&gt;
&lt;pre style=&quot;font-family: Consolas,Courier New,Courier,mono,serif; font-size:12px;&quot;&gt;
Point object internals:
OFF  SZ   TYPE DESCRIPTION               VALUE
  0   8        (object header: mark)     N/A
  8   4    int Point.x                   N/A
 12   4    int Point.y                   N/A
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total
&lt;/pre&gt;
&lt;p&gt;As shown above, with compact object headers enabled, the object header now takes 8 bytes instead of 12, a saving of 4 bytes.&lt;/p&gt;

&lt;p&gt;Previously, the object header layout was split into a &lt;code&gt;mark&lt;/code&gt; word (8 bytes) and a &lt;code&gt;class&lt;/code&gt; word (4 bytes). With compact object headers, the division between the &lt;code&gt;mark&lt;/code&gt; and &lt;code&gt;class&lt;/code&gt; words is removed, and the &lt;code&gt;class&lt;/code&gt; word is subsumed into the &lt;code&gt;mark&lt;/code&gt; word for a total of 8 bytes.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://fahdshariff.blogspot.com/feeds/2308513057814910556/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fahdshariff.blogspot.com/2025/12/java-25-compact-object-headers.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/32637828/posts/default/2308513057814910556'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/32637828/posts/default/2308513057814910556'/><link rel='alternate' type='text/html' href='http://fahdshariff.blogspot.com/2025/12/java-25-compact-object-headers.html' title='Java 25: Compact Object Headers'/><author><name>Fahd Shariff</name><uri>http://www.blogger.com/profile/00919911016127601294</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyUY9JyEBDYzkRuo6ZcCIH40ft7Uo0CcAZL_NMxtyWnKW76BmrZwDbduRP2c8taq9QAgjlVCFPvCD0Vhxbt6_xAEwolBSnviy6wI_XO00TV8trJNKlpM-HtAB4RvQf_0M/s220/mvbSKNwL.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-32637828.post-1603030242251382039</id><published>2025-12-18T09:00:00.001+00:00</published><updated>2025-12-18T09:00:00.121+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Java"/><category scheme="http://www.blogger.com/atom/ns#" term="jol"/><category scheme="http://www.blogger.com/atom/ns#" term="memory"/><category scheme="http://www.blogger.com/atom/ns#" term="programming"/><title type='text'>Measuring Java Object Size with JOL (Java Object Layout)</title><content type='html'>&lt;p&gt;&lt;a href=&quot;https://github.com/openjdk/jol&quot;&gt;JOL (Java Object Layout)&lt;/a&gt; is a small but powerful tool developed by the OpenJDK team that lets you inspect and measure how Java objects are actually laid out in memory.&lt;/p&gt;

&lt;p&gt;With JOL, you can:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;Inspect object headers and field offsets&lt;/li&gt;
    &lt;li&gt;See padding and alignment effects&lt;/li&gt;
    &lt;li&gt;Measure shallow and deep object sizes&lt;/li&gt;
    &lt;li&gt;Compare layouts across JVM configurations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let&#39;s start with the following simple class:&lt;/p&gt;

&lt;pre class=&quot;brush:java; gutter:false;&quot;&gt;
public class Point {
  int x;
  int y;
}
&lt;/pre&gt;

&lt;p&gt;Now use JOL to inspect its layout using &lt;a href=&quot;https://javadoc.io/doc/org.openjdk.jol/jol-core/0.8/org/openjdk/jol/info/ClassLayout.html&quot;&gt;&lt;code&gt;ClassLayout&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;pre class=&quot;brush:java; gutter:false;&quot;&gt;
import org.openjdk.jol.info.ClassLayout;

public class JolExample {
  public static void main(String[] args) {
    System.out.println(ClassLayout.parseClass(Point.class).toPrintable());
  }
}
&lt;/pre&gt;

&lt;p&gt;The output is:&lt;/p&gt;
&lt;pre style=&quot;font-family: Consolas,Courier New,Courier,mono,serif; font-size:12px;&quot;&gt;
Point object internals:
OFF  SZ   TYPE DESCRIPTION               VALUE
  0   8        (object header: mark)     N/A
  8   4        (object header: class)    N/A
 12   4    int Point.x                   N/A
 16   4    int Point.y                   N/A
 20   4        (object alignment gap)    
Instance size: 24 bytes
&lt;/pre&gt;

&lt;p&gt;This shows that even though the Point class only has 2 int fields requiring a total of 8 bytes, the actual object uses three times that amount (24 bytes), due to the object header (12 bytes) and alignment (4 bytes).&lt;/p&gt;

&lt;p&gt;&lt;b&gt;&lt;font color=&quot;#000099&quot;&gt;Shallow Size vs. Deep Size&lt;/font&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;The shallow size is the memory consumed by the object itself, excluding objects it references i.e. it includes the fields, object header and padding, but &lt;i&gt;not&lt;/i&gt; referenced objects.&lt;/p&gt;
&lt;p&gt;The deep size, on the other hand, includes the entire object graph reachable from the object.&lt;/p&gt;

&lt;p&gt;To demonstrate this, let&#39;s look at the following example:&lt;/p&gt;

&lt;pre class=&quot;brush:java; gutter:false;&quot;&gt;
public class Address {
  private final String city;

  public Address(String city) {
    this.city = city;
  }
}

public class Person {
  private final String name;
  private final Address address;
  private final int age;

  public Person(String name, Address address, int age) {
    this.name = name;
    this.address = address;
    this.age = age;
  }
}
&lt;/pre&gt;

&lt;p&gt;Here is the JOL output, which shows the shallow size of the &lt;code&gt;Address&lt;/code&gt; and &lt;code&gt;Person&lt;/code&gt;:&lt;/p&gt;
&lt;pre style=&quot;font-family: Consolas,Courier New,Courier,mono,serif; font-size:12px;&quot;&gt;
&lt;b&gt;&amp;gt; ClassLayout.parseClass(Address.class).toPrintable();&lt;/b&gt;

Address object internals:
OFF  SZ               TYPE DESCRIPTION               VALUE
  0   8                    (object header: mark)     N/A
  8   4                    (object header: class)    N/A
 12   4   java.lang.String Address.city              N/A
Instance size: 16 bytes

&lt;b&gt;&amp;gt; ClassLayout.parseClass(Person.class).toPrintable();&lt;/b&gt;

Person object internals:
OFF  SZ               TYPE DESCRIPTION               VALUE
  0   8                    (object header: mark)     N/A
  8   4                    (object header: class)    N/A
 12   4                int Person.age                N/A
 16   4   java.lang.String Person.name               N/A
 20   4            Address Person.address            N/A
Instance size: 24 bytes
&lt;/pre&gt;

&lt;p&gt;As shown above, the &lt;code&gt;Person&lt;/code&gt;&#39;s shallow size includes the object header, &lt;code&gt;age&lt;/code&gt; and object references (&lt;code&gt;name&lt;/code&gt; and &lt;code&gt;address&lt;/code&gt;), but does not include the &lt;code&gt;String&lt;/code&gt; object for &lt;code&gt;name&lt;/code&gt;, &lt;code&gt;Address&lt;/code&gt; object, &lt;code&gt;String&lt;/code&gt; inside &lt;code&gt;Address&lt;/code&gt;, or any backing &lt;code&gt;char[]&lt;/code&gt; or &lt;code&gt;byte[]&lt;/code&gt; arrays.&lt;/p&gt;

&lt;p&gt;To see the deep size of the &lt;code&gt;Person&lt;/code&gt;, use &lt;a href=&quot;https://javadoc.io/static/org.openjdk.jol/jol-core/0.8/org/openjdk/jol/info/GraphLayout.html&quot;&gt;&lt;code&gt;GraphLayout&lt;/code&gt;&lt;/a&gt; instead of &lt;a href=&quot;https://javadoc.io/doc/org.openjdk.jol/jol-core/0.8/org/openjdk/jol/info/ClassLayout.html&quot;&gt;&lt;code&gt;ClassLayout&lt;/code&gt;&lt;/a&gt;, like this:&lt;/p&gt;
&lt;pre class=&quot;brush:java; gutter:false;&quot;&gt;
import org.openjdk.jol.info.GraphLayout;

public class JolExample {
  public static void main(String[] args) {
    final Address address = new Address(&quot;London&quot;);
    final Person person = new Person(&quot;Alice&quot;, address, 30);
    System.out.println(GraphLayout.parseInstance(person).toFootprint());        
  }
}
&lt;/pre&gt;
&lt;p&gt;The output is:&lt;/p&gt;
&lt;pre style=&quot;font-family: Consolas,Courier New,Courier,mono,serif; font-size:12px;&quot;&gt;
Person@27abe2cdd footprint:
     COUNT       AVG       SUM   DESCRIPTION
         2        24        48   [B
         1        16        16   Address
         1        24        24   Person
         2        24        48   java.lang.String
         6                 136   (total)
&lt;/pre&gt;
&lt;p&gt;That&#39;s 136 bytes in total. Note that each String is backed by a byte array (represented by &lt;code&gt;[B&lt;/code&gt;) which is 24 bytes.&lt;/p&gt;

&lt;p&gt;Therefore, &lt;code&gt;Person&lt;/code&gt; is only 24 bytes shallow, but costs 136 bytes deep.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://fahdshariff.blogspot.com/feeds/1603030242251382039/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fahdshariff.blogspot.com/2025/12/measuring-java-object-size-with-jol.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/32637828/posts/default/1603030242251382039'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/32637828/posts/default/1603030242251382039'/><link rel='alternate' type='text/html' href='http://fahdshariff.blogspot.com/2025/12/measuring-java-object-size-with-jol.html' title='Measuring Java Object Size with JOL (Java Object Layout)'/><author><name>Fahd Shariff</name><uri>http://www.blogger.com/profile/00919911016127601294</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyUY9JyEBDYzkRuo6ZcCIH40ft7Uo0CcAZL_NMxtyWnKW76BmrZwDbduRP2c8taq9QAgjlVCFPvCD0Vhxbt6_xAEwolBSnviy6wI_XO00TV8trJNKlpM-HtAB4RvQf_0M/s220/mvbSKNwL.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-32637828.post-6250367947501887015</id><published>2025-12-16T08:00:00.001+00:00</published><updated>2025-12-16T08:00:00.124+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Linux"/><category scheme="http://www.blogger.com/atom/ns#" term="Ubuntu"/><category scheme="http://www.blogger.com/atom/ns#" term="Windows"/><category scheme="http://www.blogger.com/atom/ns#" term="wsl"/><title type='text'>Running Ubuntu on Windows 11 with WSL</title><content type='html'>&lt;p&gt;&lt;a href=&quot;https://learn.microsoft.com/en-us/windows/wsl/about&quot;&gt;Windows Subsystem for Linux (WSL)&lt;/a&gt; makes it easy to run a full Linux environment directly on Windows 11. This is great for developers and power users who want Linux tools (e.g. grep, sed, awk, tmux) alongside Windows apps.&lt;/p&gt;

&lt;p&gt;This is how you can install &lt;a href=&quot;https://ubuntu.com/desktop/wsl&quot;&gt;Ubuntu on Windows 11&lt;/a&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open PowerShell in administrator mode by right-clicking and selecting &quot;Run as administrator&quot;, run the &lt;code&gt;wsl --install&lt;/code&gt; command, and then restart your machine.&lt;/li&gt;
&lt;li&gt;Run  &lt;code&gt;wsl --list --online&lt;/code&gt; to list the distributions that can be installed, as shown below:
&lt;pre style=&quot;font-family: Consolas,Courier New,Courier,mono,serif; font-size:12px;&quot;&gt;
&lt;b&gt;PS &amp;gt; wsl --list --online&lt;/b&gt;

The following is a list of valid distributions that can be installed.
Install using &#39;wsl.exe --install &amp;lt;Distro&amp;gt;&#39;.

NAME                            FRIENDLY NAME
AlmaLinux-8                     AlmaLinux OS 8
AlmaLinux-9                     AlmaLinux OS 9
AlmaLinux-Kitten-10             AlmaLinux OS Kitten 10
AlmaLinux-10                    AlmaLinux OS 10
Debian                          Debian GNU/Linux
FedoraLinux-43                  Fedora Linux 43
FedoraLinux-42                  Fedora Linux 42
SUSE-Linux-Enterprise-15-SP7    SUSE Linux Enterprise 15 SP7
SUSE-Linux-Enterprise-16.0      SUSE Linux Enterprise 16.0
Ubuntu                          Ubuntu
Ubuntu-24.04                    Ubuntu 24.04 LTS
archlinux                       Arch Linux
kali-linux                      Kali Linux Rolling
openSUSE-Tumbleweed             openSUSE Tumbleweed
openSUSE-Leap-16.0              openSUSE Leap 16.0
Ubuntu-20.04                    Ubuntu 20.04 LTS
Ubuntu-22.04                    Ubuntu 22.04 LTS
OracleLinux_7_9                 Oracle Linux 7.9
OracleLinux_8_10                Oracle Linux 8.10
OracleLinux_9_5                 Oracle Linux 9.5
openSUSE-Leap-15.6              openSUSE Leap 15.6
SUSE-Linux-Enterprise-15-SP6    SUSE Linux Enterprise 15 SP6
&lt;/pre&gt;
&lt;li&gt;Run &lt;code&gt;wsl --install Ubuntu&lt;/code&gt; (or another distro of your choice)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That’s it! Ubuntu is now running on your Windows 11 system.&lt;/p&gt;

&lt;p&gt;You can now open a Ubuntu terminal by running the &lt;code&gt;wsl&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;You can access your Windows files from &lt;code&gt;/mnt/c&lt;/code&gt;. You can also install Ubuntu packages using &lt;code&gt;apt&lt;/code&gt;.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://fahdshariff.blogspot.com/feeds/6250367947501887015/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fahdshariff.blogspot.com/2025/12/running-ubuntu-on-windows-11-with-wsl.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/32637828/posts/default/6250367947501887015'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/32637828/posts/default/6250367947501887015'/><link rel='alternate' type='text/html' href='http://fahdshariff.blogspot.com/2025/12/running-ubuntu-on-windows-11-with-wsl.html' title='Running Ubuntu on Windows 11 with WSL'/><author><name>Fahd Shariff</name><uri>http://www.blogger.com/profile/00919911016127601294</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyUY9JyEBDYzkRuo6ZcCIH40ft7Uo0CcAZL_NMxtyWnKW76BmrZwDbduRP2c8taq9QAgjlVCFPvCD0Vhxbt6_xAEwolBSnviy6wI_XO00TV8trJNKlpM-HtAB4RvQf_0M/s220/mvbSKNwL.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-32637828.post-2303566597593381107</id><published>2025-05-03T09:00:00.001+01:00</published><updated>2025-05-03T09:00:00.118+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="concurrency"/><category scheme="http://www.blogger.com/atom/ns#" term="Java"/><category scheme="http://www.blogger.com/atom/ns#" term="java24"/><category scheme="http://www.blogger.com/atom/ns#" term="programming"/><title type='text'>Java 24: Structured Concurrency</title><content type='html'>&lt;p&gt;With &lt;a href=&quot;https://www.oracle.com/java/technologies/javase/24all-relnotes.html&quot;&gt;Java 24&lt;/a&gt;, &lt;a href=&quot;https://openjdk.org/jeps/499&quot;&gt;Structured Concurrency&lt;/a&gt; moves closer to becoming a first-class feature in the Java platform. This is currently a &lt;a href=&quot;https://openjdk.org/jeps/12&quot;&gt;preview language feature&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Traditional concurrency in Java often results in fragmented and error-prone code, where related threads are launched independently and can be hard to manage or coordinate. For example, to fetch a user and order in parallel, and then process the results, you would typically use an &lt;code&gt;ExecutorService&lt;/code&gt; as shown below:&lt;/p&gt;

&lt;pre class=&quot;brush:java; gutter:false;&quot;&gt;
ExecutorService executor = Executors.newFixedThreadPool(2);
Future&amp;lt;String&amp;gt; userFuture = executor.submit(() -&amp;gt; fetchUser());
Future&amp;lt;String&amp;gt; orderFuture = executor.submit(() -&amp;gt; fetchOrder());
String user = userFuture.get();   // blocks until user is fetched
String order = orderFuture.get(); // blocks until order is fetched
String result = process(user, order);
&lt;/pre&gt;

&lt;p&gt;The downsides of the above approach are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If one task fails, the other continues unless manually cancelled&lt;/li&gt;
&lt;li&gt;The executor and tasks outlive the method unless explicitly shut down&lt;/li&gt;
&lt;li&gt;You must manage the executor, handle exceptions, and ensure cleanup&lt;/li&gt;
&lt;/ul&gt;
 
&lt;p&gt;Structured Concurrency abstracts much of this complexity, allowing you to focus on what your code is doing rather than how to coordinate threads. It enforces a hierarchical structure, in which tasks spawned together must complete together, much like local variables within a method.&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;&lt;font color=&quot;#000099&quot;&gt;&lt;a href=&quot;https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/util/concurrent/StructuredTaskScope.html&quot;&gt;StructuredTaskScope&lt;/a&gt;&lt;/font&gt;&lt;/b&gt;&lt;br/&gt;
Here is an example of using the &lt;code&gt;StructuredTaskScope&lt;/code&gt; API:&lt;/p&gt;

&lt;pre class=&quot;brush:java; gutter:false;&quot;&gt;
try (var scope = new StructuredTaskScope&amp;lt;String&amp;gt;()) {
  Subtask&amp;lt;String&amp;gt; userTask = scope.fork(() -&amp;gt; fetchUser());
  Subtask&amp;lt;String&amp;gt; orderTask = scope.fork(() -&amp;gt; fetchOrder());

  scope.join(); // Wait for all subtasks to complete

  String user = userTask.get();
  String order = orderTask.get();

  System.out.println(&quot;user: &quot; + user);
  System.out.println(&quot;order: &quot; + order);
}
&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;StructuredTaskScope&lt;/code&gt; has two subclasses, &lt;code&gt;ShutdownOnSuccess&lt;/code&gt; and &lt;code&gt;ShutdownOnFailure&lt;/code&gt;, to control how the scope reacts to task completion or failure.&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;&lt;font color=&quot;#000099&quot;&gt;&lt;a href=&quot;https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/util/concurrent/StructuredTaskScope.ShutdownOnFailure.html&quot;&gt;StructuredTaskScope.ShutdownOnFailure&lt;/a&gt;&lt;/font&gt;&lt;/b&gt;&lt;br/&gt;
With this policy, if any task fails, the scope cancels the remaining tasks, and propagates the exception when &lt;code&gt;throwIfFailed()&lt;/code&gt; is called.
&lt;/p&gt;

&lt;pre class=&quot;brush:java; gutter:false;&quot;&gt;
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
  Subtask&amp;lt;String&amp;gt; userTask = scope.fork(() -&amp;gt; fetchUser());
  Subtask&amp;lt;String&amp;gt; orderTask = scope.fork(() -&amp;gt; fetchOrder());

  // wait for all subtasks to complete, or one to fail
  scope.join();
  
  // throw if any subtask failed 
  scope.throwIfFailed();

  String user = userTask.get();
  String order = orderTask.get();

  System.out.println(&quot;user: &quot; + user);
  System.out.println(&quot;order: &quot; + order);
}
&lt;/pre&gt;


&lt;p&gt;
&lt;b&gt;&lt;font color=&quot;#000099&quot;&gt;&lt;a href=&quot;https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/util/concurrent/StructuredTaskScope.ShutdownOnSuccess.html&quot;&gt;StructuredTaskScope.ShutdownOnSuccess&lt;/a&gt;&lt;/font&gt;&lt;/b&gt;&lt;br/&gt;
This policy is the opposite — it stops once one task succeeds, cancelling the others. It&#39;s great when you want the first successful result and don&#39;t care about the rest.
&lt;/p&gt;
&lt;pre class=&quot;brush:java; gutter:false;&quot;&gt;
try (var scope = new StructuredTaskScope.ShutdownOnSuccess&amp;lt;String&amp;gt;()) {
  scope.fork(() -&amp;gt; fetchFromPrimary());
  scope.fork(() -&amp;gt; fetchFromBackup());

  // wait for any subtask to complete, or all to fail
  scope.join();

  // get the result of the first task that completed successfully,
  // or throw an exception if none did
  System.out.println(scope.result()); 
}
&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://fahdshariff.blogspot.com/feeds/2303566597593381107/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fahdshariff.blogspot.com/2025/05/java-24-structured-concurrency.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/32637828/posts/default/2303566597593381107'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/32637828/posts/default/2303566597593381107'/><link rel='alternate' type='text/html' href='http://fahdshariff.blogspot.com/2025/05/java-24-structured-concurrency.html' title='Java 24: Structured Concurrency'/><author><name>Fahd Shariff</name><uri>http://www.blogger.com/profile/00919911016127601294</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyUY9JyEBDYzkRuo6ZcCIH40ft7Uo0CcAZL_NMxtyWnKW76BmrZwDbduRP2c8taq9QAgjlVCFPvCD0Vhxbt6_xAEwolBSnviy6wI_XO00TV8trJNKlpM-HtAB4RvQf_0M/s220/mvbSKNwL.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-32637828.post-1179006648336250073</id><published>2025-03-30T09:00:00.001+01:00</published><updated>2025-03-30T09:00:00.126+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Java"/><category scheme="http://www.blogger.com/atom/ns#" term="java24"/><category scheme="http://www.blogger.com/atom/ns#" term="programming"/><title type='text'>Java 24: Scoped Values</title><content type='html'>&lt;p&gt;&lt;a href=&quot;https://www.oracle.com/java/technologies/javase/24all-relnotes.html&quot;&gt;Java 24&lt;/a&gt; introduces &lt;a href=&quot;https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/lang/ScopedValue.html&quot;&gt;Scoped Values&lt;/a&gt;, a powerful alternative to &lt;a href=&quot;https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/lang/ThreadLocal.html&quot;&gt;&lt;code&gt;ThreadLocal&lt;/code&gt;&lt;/a&gt; that offers better performance and cleaner code for managing per-thread data. This is a &lt;a href=&quot;https://openjdk.org/jeps/487&quot;&gt;preview language feature&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here&#39;s an example of &lt;code&gt;ScopedValue&lt;/code&gt; in action:&lt;/p&gt;
&lt;pre class=&quot;brush:java; gutter:false;&quot;&gt;
private static final ScopedValue&amp;lt;String&amp;gt; USER_ID = ScopedValue.newInstance();

public void handle(Request req, String userId) {
  ScopedValue.where(USER_ID, userId)
    .run(() -&amp;gt; handle(req));
}

private void handle(Request req) {
  String data = getData(req);
  // Do something else
}

private String getData(Request req) {
  return runQuery(req, USER_ID.get());
}
&lt;/pre&gt;

&lt;p&gt;As shown above, &lt;code&gt;ScopedValue&lt;/code&gt; provides a means to pass data (the &lt;code&gt;userId&lt;/code&gt;) securely to a faraway method without using method parameters. The faraway method can access the data via the &lt;code&gt;ScopedValue&lt;/code&gt; object. This eliminates the need to pass additional parameters explicitly through multiple method calls.&lt;/p&gt;

&lt;b&gt;&lt;font color=&quot;#000099&quot;&gt;ScopedValue vs ThreadLocal&lt;/font&gt;&lt;/b&gt;&lt;br/&gt;
&lt;ul&gt;

&lt;li&gt;Scoped Values are immutable once set inside &lt;code&gt;ScopedValue.where(...)&lt;/code&gt;. On the other hand, &lt;code&gt;ThreadLocal&lt;/code&gt; allows values to be changed at any time, which can lead to inconsistent state across different parts of a request.&lt;/li&gt;

&lt;li&gt;Scoped Values are automatically removed after the scope ends, whereas &lt;code&gt;ThreadLocal&lt;/code&gt; requires an explicit call to &lt;code&gt;remove()&lt;/code&gt; to avoid memory leaks, especially in thread pools.&lt;/li&gt;

&lt;li&gt;Scoped Values bind data to a specific execution scope, ensuring that when a new task starts on a thread, it doesn’t inherit values from a previous request. &lt;code&gt;ThreadLocal&lt;/code&gt; stores data at the thread level, meaning values persist across multiple tasks when using a thread pool.&lt;/li&gt;

&lt;li&gt;Scoped Values work well with virtual threads and structured concurrency APIs.&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;For comparison, here&#39;s the same example using &lt;code&gt;ThreadLocal&lt;/code&gt;:&lt;/p&gt;

&lt;pre class=&quot;brush:java; gutter:false;&quot;&gt;
private static final ThreadLocal&amp;lt;String&amp;gt; USER_ID = new ThreadLocal&amp;lt;&amp;gt;();

public void handle(Request req, String userId) {
  try {
    USER_ID.set(userId);
    handle(req);
  } finally {
    USER_ID.remove(); // to prevent memory leaks
  }
}

private void handle(Request req) {
  String data = getData(req);
  // Do something else
}

private String getData(Request req) {
  return runQuery(req, USER_ID.get());
}
&lt;/pre&gt;

&lt;p&gt;While &lt;code&gt;ThreadLocal&lt;/code&gt; still has its uses, most new applications will benefit from Scoped Values’ immutability, automatic cleanup, and better thread management.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://fahdshariff.blogspot.com/feeds/1179006648336250073/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fahdshariff.blogspot.com/2025/03/java-24-scoped-values.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/32637828/posts/default/1179006648336250073'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/32637828/posts/default/1179006648336250073'/><link rel='alternate' type='text/html' href='http://fahdshariff.blogspot.com/2025/03/java-24-scoped-values.html' title='Java 24: Scoped Values'/><author><name>Fahd Shariff</name><uri>http://www.blogger.com/profile/00919911016127601294</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyUY9JyEBDYzkRuo6ZcCIH40ft7Uo0CcAZL_NMxtyWnKW76BmrZwDbduRP2c8taq9QAgjlVCFPvCD0Vhxbt6_xAEwolBSnviy6wI_XO00TV8trJNKlpM-HtAB4RvQf_0M/s220/mvbSKNwL.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-32637828.post-6920254476288296525</id><published>2025-03-28T14:31:00.001+00:00</published><updated>2025-03-28T15:47:48.316+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Java"/><category scheme="http://www.blogger.com/atom/ns#" term="java24"/><category scheme="http://www.blogger.com/atom/ns#" term="programming"/><title type='text'>Java 24: Primitive Types in Patterns, instanceof, and switch</title><content type='html'>&lt;p&gt;&lt;a href=&quot;https://www.oracle.com/java/technologies/javase/24all-relnotes.html&quot;&gt;Java 24&lt;/a&gt; introduces &lt;a href=&quot;https://openjdk.org/jeps/488&quot;&gt;enhancements&lt;/a&gt; to pattern matching by allowing primitive types in all pattern contexts, and extending &lt;code&gt;instanceof&lt;/code&gt; and &lt;code&gt;switch&lt;/code&gt; to work with all primitive types. This is a preview language feature.&lt;/p&gt;

&lt;p&gt;Previously, pattern matching for &lt;code&gt;switch&lt;/code&gt; only supported reference types such as &lt;code&gt;Integer i&lt;/code&gt;, but now it supports primitive types too. For example:&lt;/p&gt;

&lt;pre class=&quot;brush:java; gutter:false;&quot;&gt;
int i = 100;
String s = switch(i) {
  case 1 -&gt; &quot;one&quot;;
  case 2 -&gt; &quot;two&quot;;
  case int i when i &gt; 2 -&gt; &quot;too big&quot;;
  default -&gt; &quot;unsupported&quot;;
}
&lt;/pre&gt;

&lt;p&gt;Similarly, &lt;code&gt;instanceof&lt;/code&gt; has been enhanced to support primitives, as shown in the example below:&lt;/p&gt;

&lt;pre class=&quot;brush:java; gutter:false;&quot;&gt;
int i = 1;
if (i instanceof byte b) {
  // i has been cast to byte and assigned to b
}
&lt;/pre&gt;

&lt;b&gt;&lt;font color=&quot;#000099&quot;&gt;Related posts:&lt;/font&gt;&lt;/b&gt;&lt;br/&gt;
&lt;a href=&quot;https://fahdshariff.blogspot.com/2022/11/java-19-record-patterns.html&quot;&gt;Java 19: Record Patterns&lt;/a&gt;&lt;br/&gt;
&lt;a href=&quot;https://fahdshariff.blogspot.com/2021/09/java-17-pattern-matching-for-switch.html&quot;&gt;Java 17: Pattern Matching for Switch&lt;/a&gt;&lt;br/&gt;
&lt;a href=&quot;https://fahdshariff.blogspot.com/2020/04/java-14-pattern-matching-for-instanceof.html&quot;&gt;Java 14: Pattern Matching for instanceof&lt;/a&gt;&lt;br/&gt;</content><link rel='replies' type='application/atom+xml' href='http://fahdshariff.blogspot.com/feeds/6920254476288296525/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fahdshariff.blogspot.com/2025/03/java-24-primitive-types-in-patterns.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/32637828/posts/default/6920254476288296525'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/32637828/posts/default/6920254476288296525'/><link rel='alternate' type='text/html' href='http://fahdshariff.blogspot.com/2025/03/java-24-primitive-types-in-patterns.html' title='Java 24: Primitive Types in Patterns, instanceof, and switch'/><author><name>Fahd Shariff</name><uri>http://www.blogger.com/profile/00919911016127601294</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyUY9JyEBDYzkRuo6ZcCIH40ft7Uo0CcAZL_NMxtyWnKW76BmrZwDbduRP2c8taq9QAgjlVCFPvCD0Vhxbt6_xAEwolBSnviy6wI_XO00TV8trJNKlpM-HtAB4RvQf_0M/s220/mvbSKNwL.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-32637828.post-5884097548296263178</id><published>2025-01-01T09:00:00.001+00:00</published><updated>2025-01-01T09:00:00.226+00:00</updated><title type='text'>fahd.blog in 2024</title><content type='html'>&lt;p&gt;&lt;b&gt;&lt;font color=&quot;#000099&quot;&gt;Happy 2025, everyone!&lt;/font&gt;&lt;/b&gt;&lt;/p&gt;&lt;p&gt;I&#39;d like to wish everyone a great start to an even greater new year!&lt;/p&gt;

&lt;p&gt;In keeping with tradition, here&#39;s one last look back at &lt;a href=&quot;http://fahdshariff.blogspot.com&quot;&gt;fahd.blog&lt;/a&gt; in 2024.&lt;/p&gt;

&lt;p&gt;During 2024, I posted 10 new entries on &lt;a href=&quot;http://fahdshariff.blogspot.com&quot;&gt;fahd.blog&lt;/a&gt;. I am also thrilled that I have more readers from all over the world! Thanks for reading and especially for giving feedback.&lt;/p&gt;

&lt;b&gt;&lt;font color=&quot;#000099&quot;&gt;Top 3 posts of 2024:&lt;/font&gt;&lt;/b&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://fahdshariff.blogspot.com/2024/05/calling-python-functions-from-kdbq-with.html&quot;&gt;Calling Python Functions from kdb+/q with PyKX&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://fahdshariff.blogspot.com/2024/05/using-mathml-to-embed-mathematical.html&quot;&gt;Using MathML to Embed Mathematical Equations in Webpages&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://fahdshariff.blogspot.com/2024/08/web-workers.html&quot;&gt;Web Workers&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I&#39;m going to be writing a lot more this year, so stay tuned for more great techie tips, tricks and hacks! :)&lt;/p&gt;

&lt;b&gt;&lt;font color=&quot;#000099&quot;&gt;Related posts:&lt;/font&gt;&lt;/b&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://fahdshariff.blogspot.com/2024/01/fahdblog-in-2023.html&quot;&gt;fahd.blog in 2023&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://fahdshariff.blogspot.com/2023/01/fahdblog-in-2022.html&quot;&gt;fahd.blog in 2022&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://fahdshariff.blogspot.com/2022/01/fahdblog-in-2021.html&quot;&gt;fahd.blog in 2021&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://fahdshariff.blogspot.com/2021/01/fahdblog-in-2020.html&quot;&gt;fahd.blog in 2020&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://fahdshariff.blogspot.com/2020/01/fahdblog-in-2019.html&quot;&gt;fahd.blog in 2019&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://fahdshariff.blogspot.com/2019/01/fahdblog-in-2018.html&quot;&gt;fahd.blog in 2018&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://fahdshariff.blogspot.com/2018/01/fahdblog-in-2017.html&quot;&gt;fahd.blog in 2017&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://fahdshariff.blogspot.com/2017/01/fahdblog-in-2016.html&quot;&gt;fahd.blog in 2016&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://fahdshariff.blogspot.com/2016/01/fahdblog-in-2015.html&quot;&gt;fahd.blog in 2015&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://fahdshariff.blogspot.com/2015/01/fahdblog-in-2014.html&quot;&gt;fahd.blog in 2014&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://fahdshariff.blogspot.com/2014/01/fahdblog-in-2013.html&quot;&gt;fahd.blog in 2013&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><link rel='replies' type='application/atom+xml' href='http://fahdshariff.blogspot.com/feeds/5884097548296263178/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fahdshariff.blogspot.com/2025/01/fahdblog-in-2024.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/32637828/posts/default/5884097548296263178'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/32637828/posts/default/5884097548296263178'/><link rel='alternate' type='text/html' href='http://fahdshariff.blogspot.com/2025/01/fahdblog-in-2024.html' title='fahd.blog in 2024'/><author><name>Fahd Shariff</name><uri>http://www.blogger.com/profile/00919911016127601294</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyUY9JyEBDYzkRuo6ZcCIH40ft7Uo0CcAZL_NMxtyWnKW76BmrZwDbduRP2c8taq9QAgjlVCFPvCD0Vhxbt6_xAEwolBSnviy6wI_XO00TV8trJNKlpM-HtAB4RvQf_0M/s220/mvbSKNwL.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-32637828.post-2235776632679971145</id><published>2024-08-24T09:00:00.005+01:00</published><updated>2024-08-24T09:00:00.120+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="blob"/><category scheme="http://www.blogger.com/atom/ns#" term="html"/><category scheme="http://www.blogger.com/atom/ns#" term="javascript"/><category scheme="http://www.blogger.com/atom/ns#" term="programming"/><category scheme="http://www.blogger.com/atom/ns#" term="web"/><title type='text'>JavaScript Blobs</title><content type='html'>&lt;p&gt;A &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Blob&quot;&gt;Blob&lt;/a&gt; (Binary Large Object) is a data structure used to store raw data. It can be created using the Blob constructor. For instance:&lt;/p&gt;
&lt;pre class=&quot;brush:jscript; gutter:false;&quot;&gt;
const myBlob = new Blob([&#39;Hello, world!&#39;], { type: &#39;text/plain&#39; });
&lt;/pre&gt;

&lt;p&gt;You can use Blobs to create URLs, which can be directly embedded into HTML documents. For example, you can create a Blob containing text data and then generate a download link for it. When the user clicks this link, they can download the Blob content as a file. This is shown below:&lt;/p&gt;

&lt;pre class=&quot;brush:java; gutter:false;&quot;&gt;
&amp;lt;html&amp;gt;
&amp;lt;head/&amp;gt;
&amp;lt;body&amp;gt;
  &amp;lt;h1&amp;gt;Download Blob Example&amp;lt;/h1&amp;gt;

  &amp;lt;script&amp;gt;
    const createDownloadLink = (content, filename) =&amp;gt; {
      // Create a Blob from the content
      const blob = new Blob([content], { type: &#39;text/plain&#39; });
      
      // Create a URL for the Blob
      const url = URL.createObjectURL(blob);
      
      // Create an &amp;lt;a&amp;gt; element
      const a = document.createElement(&#39;a&#39;);
      a.href = url;
      a.download = filename;
      a.textContent = `Download ${filename}`;

      // append to body
      document.body.appendChild(a);
      
      // revoke URL after some time or on user action
      // URL.revokeObjectURL(url); 
    }
    createDownloadLink(&#39;some content&#39;, &#39;example.txt&#39;);
  &amp;lt;/script&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/pre&gt;

&lt;p&gt;You can also use a Blob to dynamically generate code and create JavaScript files on-the-fly! Here’s an example of how to create a Web Worker from a Blob:&lt;/p&gt;


&lt;pre class=&quot;brush:java; gutter:false;&quot;&gt;
&amp;lt;html&amp;gt;
&amp;lt;head/&amp;gt;
&amp;lt;body&amp;gt;
  &amp;lt;h1&amp;gt;Web Worker Blob Example&amp;lt;/h1&amp;gt;
  &amp;lt;p id=&quot;result&quot;&amp;gt;&amp;lt;/p&amp;gt;

  &amp;lt;script&amp;gt;
    const workerScript = `
      onmessage = e =&amp;gt; {
        postMessage(e.data * 2);
      };
    `;

    const blob = new Blob([workerScript], { type: &#39;application/javascript&#39; });
    const url = URL.createObjectURL(blob);
    const worker = new Worker(url);

    worker.onmessage = e =&amp;gt; {
      document.getElementById(&#39;result&#39;).textContent = &#39;Worker result: &#39; + e.data;
      URL.revokeObjectURL(url); // Clean up Blob URL
    };

    worker.postMessage(&#39;2&#39;);
  &amp;lt;/script&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;

&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://fahdshariff.blogspot.com/feeds/2235776632679971145/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fahdshariff.blogspot.com/2024/08/javascript-blobs.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/32637828/posts/default/2235776632679971145'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/32637828/posts/default/2235776632679971145'/><link rel='alternate' type='text/html' href='http://fahdshariff.blogspot.com/2024/08/javascript-blobs.html' title='JavaScript Blobs'/><author><name>Fahd Shariff</name><uri>http://www.blogger.com/profile/00919911016127601294</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyUY9JyEBDYzkRuo6ZcCIH40ft7Uo0CcAZL_NMxtyWnKW76BmrZwDbduRP2c8taq9QAgjlVCFPvCD0Vhxbt6_xAEwolBSnviy6wI_XO00TV8trJNKlpM-HtAB4RvQf_0M/s220/mvbSKNwL.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-32637828.post-5214103566912478086</id><published>2024-08-10T21:56:00.002+01:00</published><updated>2024-08-10T21:56:00.228+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="html"/><category scheme="http://www.blogger.com/atom/ns#" term="html5"/><category scheme="http://www.blogger.com/atom/ns#" term="javascript"/><category scheme="http://www.blogger.com/atom/ns#" term="programming"/><category scheme="http://www.blogger.com/atom/ns#" term="web"/><category scheme="http://www.blogger.com/atom/ns#" term="web workers"/><title type='text'>Shared Web Workers</title><content type='html'>&lt;p&gt;In my &lt;a href=&quot;https://fahdshariff.blogspot.com/2024/08/web-workers.html&quot;&gt;previous post&lt;/a&gt;, I discussed how Web Workers can be used to enhance the responsiveness of web applications by offloading resource-intensive computations to run in the background, thus preventing them from blocking the main thread. Today, let&#39;s look into Shared Web Workers and how they can further boost your app&#39;s efficiency.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/SharedWorker&quot;&gt;Shared Web Workers&lt;/a&gt; are a special type of Web Worker that can be accessed from multiple browsing contexts, such as different tabs, windows, or iframes. This shared access can facilitate various functionalities, including real-time communication, managing shared state, and caching data across multiple tabs or windows. By reusing a single worker instance, Shared Web Workers help reduce memory consumption and improve performance compared to creating a new worker for each context.&lt;/p&gt;

&lt;p&gt;The following example shows the basics of using a Shared Web Worker.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;&lt;font color=&quot;#000099&quot;&gt;1. Create the Shared Web Worker Script&lt;/font&gt;&lt;/b&gt;&lt;br/&gt;
&lt;p&gt;Shared Web Workers use ports to communicate. You need to handle the &lt;code&gt;onconnect&lt;/code&gt; event to establish communication with the port and the &lt;code&gt;onmessage&lt;/code&gt; event to process incoming messages.&lt;/p&gt;
&lt;pre class=&quot;brush:java; gutter:false;&quot;&gt;
// worker.js
onconnect = (event) =&gt; {
  const port = event.ports[0];
  port.onmessage = (e) =&gt; {
    port.postMessage(e.data[0] + e.data[1]);
  };
};
&lt;/pre&gt;

&lt;p&gt;&lt;b&gt;&lt;font color=&quot;#000099&quot;&gt;2. Use the Shared Web Worker in Your Main Script&lt;/font&gt;&lt;/b&gt;&lt;br/&gt;
&lt;p&gt;In your main script, initialise the Shared Web Worker. This can be done from multiple scripts or HTML pages. Once created, any script running on the same origin can access the worker and communicate with it. The various scripts will use the same worker for tasks, even if they are running in different windows.&lt;/p&gt;

&lt;pre class=&quot;brush:java; gutter:false;&quot;&gt;
&amp;lt;html&amp;gt;
  &amp;lt;head/&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;h1&amp;gt;Shared Web Worker Example&amp;lt;/h1&amp;gt;
    &amp;lt;p id=&quot;result&quot;&amp;gt;Computing...&amp;lt;/p&amp;gt;
    &amp;lt;script&amp;gt;
      const worker = new SharedWorker(&#39;path/to/worker.js&#39;);
      worker.port.onmessage = (e) =&amp;gt; {
        document.getElementById(&#39;result&#39;).textContent = `Result: ${e.data}`;
      };
      worker.port.postMessage([1, 2]);
    &amp;lt;/script&amp;gt;
  &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/pre&gt;

&lt;p&gt;Communication between the main script and the Shared Web Worker is done using the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/MessagePort/postMessage&quot;&gt;&lt;code&gt;port.postMessage&lt;/code&gt;&lt;/a&gt; method to send messages and the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/MessagePort/message_event&quot;&gt;&lt;code&gt;port.onmessage&lt;/code&gt;&lt;/a&gt; event to receive messages.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;&lt;font color=&quot;#000099&quot;&gt;Related posts:&lt;/font&gt;&lt;/b&gt;&lt;br/&gt;
  &lt;a href=&quot;https://fahdshariff.blogspot.com/2024/08/web-workers.html&quot;&gt;Web Workers&lt;/a&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://fahdshariff.blogspot.com/feeds/5214103566912478086/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fahdshariff.blogspot.com/2024/08/shared-web-workers.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/32637828/posts/default/5214103566912478086'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/32637828/posts/default/5214103566912478086'/><link rel='alternate' type='text/html' href='http://fahdshariff.blogspot.com/2024/08/shared-web-workers.html' title='Shared Web Workers'/><author><name>Fahd Shariff</name><uri>http://www.blogger.com/profile/00919911016127601294</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyUY9JyEBDYzkRuo6ZcCIH40ft7Uo0CcAZL_NMxtyWnKW76BmrZwDbduRP2c8taq9QAgjlVCFPvCD0Vhxbt6_xAEwolBSnviy6wI_XO00TV8trJNKlpM-HtAB4RvQf_0M/s220/mvbSKNwL.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-32637828.post-4780594682046358091</id><published>2024-08-03T10:00:00.005+01:00</published><updated>2024-08-03T10:00:00.223+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="html"/><category scheme="http://www.blogger.com/atom/ns#" term="html5"/><category scheme="http://www.blogger.com/atom/ns#" term="javascript"/><category scheme="http://www.blogger.com/atom/ns#" term="programming"/><category scheme="http://www.blogger.com/atom/ns#" term="react"/><category scheme="http://www.blogger.com/atom/ns#" term="web"/><category scheme="http://www.blogger.com/atom/ns#" term="web workers"/><title type='text'>Web Workers</title><content type='html'>&lt;p&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API&quot;&gt;Web Workers&lt;/a&gt; allow you to perform resource-intensive computations in background threads, without blocking the main thread that handles user interactions and UI updates. This makes it possible to perform tasks such as data processing, complex calculations, and large data fetching asynchronously, keeping your web application responsive.&lt;/p&gt;

&lt;p&gt;The following example shows the basics of using a web worker to perform a simple &quot;sum&quot; calculation.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;&lt;font color=&quot;#000099&quot;&gt;1. Create a Web Worker Script&lt;/font&gt;&lt;/b&gt;&lt;br/&gt;
&lt;p&gt;First, create your web worker script:&lt;/p&gt;
&lt;pre class=&quot;brush:java; gutter:false;&quot;&gt;
// worker.js
onmessage = (e) =&amp;gt; {
  const workerResult = e.data[0] + e.data[1];
  postMessage(workerResult);
};
&lt;/pre&gt;

&lt;p&gt;As shown above, the web worker performs the computation in the &lt;code&gt;onmessage&lt;/code&gt; event handler and then calls &lt;code&gt;postMessage&lt;/code&gt;, to post the result back to the main thread.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;&lt;font color=&quot;#000099&quot;&gt;2. Invoke the Web Worker in Your Main Script&lt;/font&gt;&lt;/b&gt;&lt;br/&gt;
&lt;p&gt;In the main script, initialise the web worker and invoke it with some data:&lt;/p&gt;

&lt;pre class=&quot;brush:java; gutter:false;&quot;&gt;
&amp;lt;html&amp;gt;
  &amp;lt;head/&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;h1&amp;gt;Web Worker Example&amp;lt;/h1&amp;gt;
    &amp;lt;p id=&quot;result&quot;&amp;gt;Computing...&amp;lt;/p&amp;gt;
    &amp;lt;script&amp;gt;
      const worker = new Worker(&#39;worker.js&#39;);
      worker.onmessage = (e) =&amp;gt; {
        document.getElementById(&#39;result&#39;).textContent = `Result: ${e.data}`;
      };
      worker.postMessage([1, 2]);
    &amp;lt;/script&amp;gt;
  &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/pre&gt;

&lt;p&gt;Communication between the main script and the web worker is done using the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Worker/postMessage&quot;&gt;&lt;code&gt;postMessage&lt;/code&gt;&lt;/a&gt; method to send messages and the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Worker/message_event&quot;&gt;&lt;code&gt;onmessage&lt;/code&gt;&lt;/a&gt; event to receive messages.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;&lt;font color=&quot;#000099&quot;&gt;React Example&lt;/font&gt;&lt;/b&gt;&lt;br/&gt;
&lt;p&gt;Here is how you would do it in React:&lt;/p&gt;

&lt;pre class=&quot;brush:java; gutter:false;&quot;&gt;
import React, { useState } from &#39;react&#39;;

const App = () =&amp;gt; {
  const [result, setResult] = useState(null);

  const handleClick = () =&amp;gt; {
    // Create a new Web Worker
    const worker = new Worker(new URL(&#39;./worker.js&#39;, import.meta.url));

    // Set up message handler
    worker.onmessage = (e) =&amp;gt; {
      setResult(e.data);
      worker.terminate(); // Clean up the worker
    };

    // send data to the worker
    worker.postMessage([1, 2]);
  };

  return (
    &amp;lt;div&amp;gt;
      &amp;lt;h1&amp;gt;Simple Web Worker Example&amp;lt;/h1&amp;gt;
      &amp;lt;button onClick={handleClick}&amp;gt;Start Computation&amp;lt;/button&amp;gt;
      {result !== null &amp;&amp; &amp;lt;p&amp;gt;Result from Worker: {result}&amp;lt;/p&amp;gt;}
    &amp;lt;/div&amp;gt;
  );
};
export default App;
&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://fahdshariff.blogspot.com/feeds/4780594682046358091/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fahdshariff.blogspot.com/2024/08/web-workers.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/32637828/posts/default/4780594682046358091'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/32637828/posts/default/4780594682046358091'/><link rel='alternate' type='text/html' href='http://fahdshariff.blogspot.com/2024/08/web-workers.html' title='Web Workers'/><author><name>Fahd Shariff</name><uri>http://www.blogger.com/profile/00919911016127601294</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyUY9JyEBDYzkRuo6ZcCIH40ft7Uo0CcAZL_NMxtyWnKW76BmrZwDbduRP2c8taq9QAgjlVCFPvCD0Vhxbt6_xAEwolBSnviy6wI_XO00TV8trJNKlpM-HtAB4RvQf_0M/s220/mvbSKNwL.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-32637828.post-7473224701912088155</id><published>2024-05-22T21:30:00.000+01:00</published><updated>2024-05-22T21:30:48.345+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="kdb"/><category scheme="http://www.blogger.com/atom/ns#" term="programming"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="q"/><title type='text'>Calling Python Functions from kdb+/q with PyKX</title><content type='html'>&lt;p&gt;&lt;a href=&quot;https://code.kx.com/pykx/&quot;&gt;PyKX&lt;/a&gt; allows you to call Python functions from kdb+/q (and vice versa), enabling powerful data analysis using the rich ecosystem of libraries available in Python. In this post, I will show how you can invoke a Lasso Regression function in Python by passing a table from a q script.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;&lt;font color=&quot;#000099&quot;&gt;1. Install PyKX&lt;/font&gt;&lt;/b&gt;&lt;br/&gt;
&lt;pre style=&quot;font-family: Consolas,Courier New,Courier,mono,serif; font-size:12px;background:black;color:white&quot;&gt;
pip install &lt;font color=&quot;00FFFF&quot;&gt;pykx&lt;/font&gt;
&lt;/pre&gt;

&lt;p&gt;&lt;b&gt;&lt;font color=&quot;#000099&quot;&gt;2. Create a Python (.p) file&lt;/font&gt;&lt;/b&gt;&lt;br/&gt;
&lt;p&gt;Create a Python file called &lt;code&gt;lasso.p&lt;/code&gt; containing a function that takes a Pandas DataFrame, performs Lasso regression (using the &lt;a href=&quot;https://scikit-learn.org&quot;&gt;scikit-learn&lt;/a&gt; machine learning library), and returns a vector of coefficients.&lt;/p&gt;
&lt;pre class=&quot;brush:python;gutter:false;&quot;&gt;
# lasso.p

import numpy as np
import pandas as pd
from sklearn.linear_model import Lasso

def lasso_regression(df):
    X = df.iloc[:, :-1]
    y = df.iloc[:, -1]

    # Perform Lasso regression
    lasso = Lasso(alpha=0.1)
    lasso.fit(X, y)

    coefficients = np.append(lasso.coef_, lasso.intercept_) 
    return coefficients
&lt;/pre&gt;

&lt;p&gt;&lt;b&gt;&lt;font color=&quot;#000099&quot;&gt;3. Invoke the Python function from a q script&lt;/font&gt;&lt;/b&gt;&lt;br/&gt;
&lt;p&gt;Next, write a q script that generates a table of random data and invokes the Python function with it.&lt;/p&gt;

&lt;pre style=&quot;font-family: Consolas,Courier New,Courier,mono,serif; font-size:12px;background:black;color:white&quot;&gt;
&lt;font color=&quot;#ff7f2a&quot;&gt;// Load pykx and the python file&lt;/font&gt;
\l /path/to/python/site-packages/pykx/pykx.q
\l lasso.p

&lt;font color=&quot;#ff7f2a&quot;&gt;// Create a sample table with random x and y values&lt;/font&gt;
n:100;
x:n&lt;font color=&quot;00FFFF&quot;&gt;?&lt;/font&gt;10f;
y:2&lt;font color=&quot;00FFFF&quot;&gt;*&lt;/font&gt;x&lt;font color=&quot;00FFFF&quot;&gt;+&lt;/font&gt;n&lt;font color=&quot;00FFFF&quot;&gt;?&lt;/font&gt;2f;
data:([]x;y);

&lt;font color=&quot;#ff7f2a&quot;&gt;// Call the python function&lt;/font&gt;
qfunc:&lt;font color=&quot;00FFFF&quot;&gt;.pykx.get&lt;/font&gt;[&lt;font color=&quot;#4AF626&quot;&gt;`lasso_regression&lt;/font&gt;;&amp;lt;];
coefficients:&lt;font color=&quot;00FFFF&quot;&gt;qfunc&lt;/font&gt; data;
&lt;/pre&gt;

&lt;p&gt;&lt;b&gt;&lt;font color=&quot;#000099&quot;&gt;Conversion of data types between kdb+/q and Python&lt;/font&gt;&lt;/b&gt;&lt;br/&gt;
&lt;p&gt;When transferring data between q and Python, PyKX applies &quot;default&quot; type conversions. For instance, tables in q are automatically converted to Pandas DataFrames, and lists are converted to NumPy arrays. You can call &lt;a href=&quot;https://code.kx.com/pykx/2.5/pykx-under-q/api.html#pykxsetdefault&quot;&gt;&lt;code&gt;.pykx.setdefault&lt;/code&gt;&lt;/a&gt; to change the default conversion type to Pandas, Numpy, Python, or PyArrow. PyKX also provides functions to convert q data types to specific Python types, such as &lt;a href=&quot;https://code.kx.com/pykx/2.5/pykx-under-q/api.html#pykxtonp&quot;&gt;&lt;code&gt;.pykx.tonp&lt;/code&gt;&lt;/a&gt; which tags a q object to be converted to a NumPy object. The following code illustrates type conversion:&lt;/p&gt;


&lt;pre style=&quot;font-family: Consolas,Courier New,Courier,mono,serif; font-size:12px;background:black;color:white&quot;&gt;
q) .pykx.util.defaultConv
&lt;font color=&quot;#4AF626&quot;&gt;&quot;default&quot;&lt;/font&gt;

&lt;font color=&quot;#ff7f2a&quot;&gt;// lists are converted to NumPy arrays by default&lt;/font&gt;
q) .pykx.print .pykx.eval[&quot;lambda x: type(x)&quot;] &lt;font color=&quot;00FFFF&quot;&gt;til 10&lt;/font&gt;
&lt;font color=&quot;#4AF626&quot;&gt;&amp;lt;class &#39;numpy.ndarray&#39;&amp;gt;&lt;/font&gt;

&lt;font color=&quot;#ff7f2a&quot;&gt;// tables are converted to Pandas DataFrames by default&lt;/font&gt;
q) .pykx.print .pykx.eval[&quot;lambda x: type(x)&quot;] &lt;font color=&quot;00FFFF&quot;&gt;([] foo:1 2)&lt;/font&gt;
&lt;font color=&quot;#4AF626&quot;&gt;&amp;lt;class &#39;pandas.core.frame.DataFrame&#39;&amp;gt;&lt;/font&gt;

&lt;font color=&quot;#ff7f2a&quot;&gt;// change default conversion to NumPy&lt;/font&gt;
q) .pykx.setdefault[&quot;Numpy&quot;]

&lt;font color=&quot;#ff7f2a&quot;&gt;// tables are NumPy arrays now&lt;/font&gt;
q) .pykx.print .pykx.eval[&quot;lambda x: type(x)&quot;] &lt;font color=&quot;00FFFF&quot;&gt;([] foo:1 2)&lt;/font&gt;
&lt;font color=&quot;#4AF626&quot;&gt;&amp;lt;class &#39;numpy.recarray&#39;&amp;gt;&lt;/font&gt;

&lt;font color=&quot;#ff7f2a&quot;&gt;// change default conversion to Python&lt;/font&gt;
q) .pykx.setdefault[&quot;Python&quot;]

&lt;font color=&quot;#ff7f2a&quot;&gt;// tables are converted to dict when using Python conversion&lt;/font&gt;
q) .pykx.print .pykx.eval[&quot;lambda x: type(x)&quot;] &lt;font color=&quot;00FFFF&quot;&gt;([] foo:1 2)&lt;/font&gt;
&lt;font color=&quot;#4AF626&quot;&gt;&amp;lt;class &#39;dict&#39;&amp;gt;&lt;/font&gt;

&lt;font color=&quot;#ff7f2a&quot;&gt;// tag a q object as a Pandas DataFrame&lt;/font&gt;
q) .pykx.print .pykx.eval[&quot;lambda x: type(x)&quot;] &lt;font color=&quot;00FFFF&quot;&gt;.pykx.topd ([] foo:1 2)&lt;/font&gt;
&lt;font color=&quot;#4AF626&quot;&gt;&amp;lt;class &#39;pandas.core.frame.DataFrame&#39;&amp;gt;&lt;/font&gt;
&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://fahdshariff.blogspot.com/feeds/7473224701912088155/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fahdshariff.blogspot.com/2024/05/calling-python-functions-from-kdbq-with.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/32637828/posts/default/7473224701912088155'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/32637828/posts/default/7473224701912088155'/><link rel='alternate' type='text/html' href='http://fahdshariff.blogspot.com/2024/05/calling-python-functions-from-kdbq-with.html' title='Calling Python Functions from kdb+/q with PyKX'/><author><name>Fahd Shariff</name><uri>http://www.blogger.com/profile/00919911016127601294</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyUY9JyEBDYzkRuo6ZcCIH40ft7Uo0CcAZL_NMxtyWnKW76BmrZwDbduRP2c8taq9QAgjlVCFPvCD0Vhxbt6_xAEwolBSnviy6wI_XO00TV8trJNKlpM-HtAB4RvQf_0M/s220/mvbSKNwL.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-32637828.post-2987891180933745180</id><published>2024-05-18T10:00:00.001+01:00</published><updated>2024-05-18T10:00:00.266+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="mathml"/><title type='text'>Using MathML to Embed Mathematical Equations in Webpages</title><content type='html'>&lt;p&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/MathML&quot;&gt;MathML (Mathematical Markup Language)&lt;/a&gt;, a markup language developed by the World Wide Web Consortium (W3C), serves as the standard for representing mathematical notation on the web. Integrating MathML into webpages involves encapsulating mathematical expressions within &lt;code&gt;&amp;lt;math&amp;gt;&lt;/code&gt; tags and utilising a variety of MathML elements to represent different components of equations.&lt;/p&gt;

&lt;p&gt;For example, the following snippet represents the quadratic formula:
&lt;math&gt;
  &lt;mrow&gt;
    &lt;mi&gt;x&lt;/mi&gt;
    &lt;mo&gt;=&lt;/mo&gt;
    &lt;mfrac&gt;
      &lt;mrow&gt;
        &lt;mo&gt;-&lt;/mo&gt;
        &lt;mi&gt;b&lt;/mi&gt;
        &lt;mo&gt;±&lt;/mo&gt;
        &lt;msqrt&gt;
          &lt;mrow&gt;
            &lt;msup&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msup&gt;
            &lt;mo&gt;-&lt;/mo&gt;
            &lt;mn&gt;4&lt;/mn&gt;
            &lt;mi&gt;a&lt;/mi&gt;
            &lt;mi&gt;c&lt;/mi&gt;
          &lt;/mrow&gt;
        &lt;/msqrt&gt;
      &lt;/mrow&gt;
      &lt;mrow&gt;
        &lt;mn&gt;2&lt;/mn&gt;
        &lt;mi&gt;a&lt;/mi&gt;
      &lt;/mrow&gt;
    &lt;/mfrac&gt;
  &lt;/mrow&gt;
&lt;/math&gt;
&lt;/p&gt;

&lt;pre class=&quot;brush:xml; gutter:false;&quot;&gt;
&amp;lt;math&amp;gt;
  &amp;lt;mrow&amp;gt;
    &amp;lt;mi&amp;gt;x&amp;lt;/mi&amp;gt;
    &amp;lt;mo&amp;gt;=&amp;lt;/mo&amp;gt;
    &amp;lt;mfrac&amp;gt;
      &amp;lt;mrow&amp;gt;
        &amp;lt;mo&amp;gt;-&amp;lt;/mo&amp;gt;
        &amp;lt;mi&amp;gt;b&amp;lt;/mi&amp;gt;
        &amp;lt;mo&amp;gt;±&amp;lt;/mo&amp;gt;
        &amp;lt;msqrt&amp;gt;
          &amp;lt;mrow&amp;gt;
            &amp;lt;msup&amp;gt;&amp;lt;mi&amp;gt;b&amp;lt;/mi&amp;gt;&amp;lt;mn&amp;gt;2&amp;lt;/mn&amp;gt;&amp;lt;/msup&amp;gt;
            &amp;lt;mo&amp;gt;-&amp;lt;/mo&amp;gt;
            &amp;lt;mn&amp;gt;4&amp;lt;/mn&amp;gt;
            &amp;lt;mi&amp;gt;a&amp;lt;/mi&amp;gt;
            &amp;lt;mi&amp;gt;c&amp;lt;/mi&amp;gt;
          &amp;lt;/mrow&amp;gt;
        &amp;lt;/msqrt&amp;gt;
      &amp;lt;/mrow&amp;gt;
      &amp;lt;mrow&amp;gt;
        &amp;lt;mn&amp;gt;2&amp;lt;/mn&amp;gt;
        &amp;lt;mi&amp;gt;a&amp;lt;/mi&amp;gt;
      &amp;lt;/mrow&amp;gt;
    &amp;lt;/mfrac&amp;gt;
  &amp;lt;/mrow&amp;gt;
&amp;lt;/math&amp;gt;
&lt;/pre&gt;

&lt;p&gt;While alternatives like &lt;a href=&quot;https://www.latex-project.org/&quot;&gt;LaTeX&lt;/a&gt; exist, MathML emerges as the superior choice for the web because it is supported natively by modern web browsers, without the need for additional libraries or plugins. Also, search engines can parse MathML-encoded equations, enhancing the discoverability of mathematical content on the web. LaTeX requires additional processing and rendering engines like MathJax or KaTeX to display equations in webpages, introducing complexities and potential compatibility issues.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://fahdshariff.blogspot.com/feeds/2987891180933745180/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fahdshariff.blogspot.com/2024/05/using-mathml-to-embed-mathematical.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/32637828/posts/default/2987891180933745180'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/32637828/posts/default/2987891180933745180'/><link rel='alternate' type='text/html' href='http://fahdshariff.blogspot.com/2024/05/using-mathml-to-embed-mathematical.html' title='Using MathML to Embed Mathematical Equations in Webpages'/><author><name>Fahd Shariff</name><uri>http://www.blogger.com/profile/00919911016127601294</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyUY9JyEBDYzkRuo6ZcCIH40ft7Uo0CcAZL_NMxtyWnKW76BmrZwDbduRP2c8taq9QAgjlVCFPvCD0Vhxbt6_xAEwolBSnviy6wI_XO00TV8trJNKlpM-HtAB4RvQf_0M/s220/mvbSKNwL.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-32637828.post-7258196631059693358</id><published>2024-05-11T09:00:00.002+01:00</published><updated>2024-05-11T09:15:16.495+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Java"/><category scheme="http://www.blogger.com/atom/ns#" term="java22"/><category scheme="http://www.blogger.com/atom/ns#" term="programming"/><title type='text'>Java 22: Stream Gatherers</title><content type='html'>&lt;p&gt;&lt;a href=&quot;https://www.oracle.com/java/technologies/javase/22-relnote-issues.html&quot;&gt;Java 22&lt;/a&gt; introduces &lt;a href=&quot;https://docs.oracle.com/en%2Fjava%2Fjavase%2F22%2Fdocs%2Fapi%2F%2F/java.base/java/util/stream/Gatherer.html&quot;&gt;Stream Gatherers&lt;/a&gt;, a &lt;a href=&quot;https://openjdk.org/jeps/461&quot;&gt;preview language feature&lt;/a&gt;, that allows you to build complex stream pipelines using custom intermediate operations, such as grouping elements based on specific criteria, selecting elements with intricate conditions, or performing sophisticated transformations. Furthermore, Stream Gatherers offer seamless integration with parallel stream processing, ensuring optimal performance even in parallel execution scenarios.&lt;/p&gt;

&lt;p&gt;There are built-in &lt;a href=&quot;https://docs.oracle.com/en%2Fjava%2Fjavase%2F22%2Fdocs%2Fapi%2F%2F/java.base/java/util/stream/Gatherers.html&quot;&gt;gatherers&lt;/a&gt; like &lt;code&gt;fold&lt;/code&gt;, &lt;code&gt;mapConcurrent&lt;/code&gt;, &lt;code&gt;scan&lt;/code&gt;, &lt;code&gt;windowFixed&lt;/code&gt;, and &lt;code&gt;windowSliding&lt;/code&gt;, but you can also define your own custom gatherers.&lt;/p&gt;

&lt;p&gt;Here is an example using the &lt;a href=&quot;https://docs.oracle.com/en%2Fjava%2Fjavase%2F22%2Fdocs%2Fapi%2F%2F/java.base/java/util/stream/Gatherers.html#windowSliding(int)&quot;&gt;&lt;code&gt;windowFixed&lt;/code&gt;&lt;/a&gt; gatherer to group elements in a stream into sliding windows of a specified size:&lt;/p&gt;

&lt;pre class=&quot;brush:java; gutter:false;&quot;&gt;
IntStream.range(0,10)
  .boxed()
  .gather(Gatherers.windowFixed(2))
  .forEach(System.out::println);

// Result:
[0, 1]
[2, 3]
[4, 5]
[6, 7]
[8, 9]
&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://fahdshariff.blogspot.com/feeds/7258196631059693358/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fahdshariff.blogspot.com/2024/05/java-22-stream-gatherers.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/32637828/posts/default/7258196631059693358'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/32637828/posts/default/7258196631059693358'/><link rel='alternate' type='text/html' href='http://fahdshariff.blogspot.com/2024/05/java-22-stream-gatherers.html' title='Java 22: Stream Gatherers'/><author><name>Fahd Shariff</name><uri>http://www.blogger.com/profile/00919911016127601294</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyUY9JyEBDYzkRuo6ZcCIH40ft7Uo0CcAZL_NMxtyWnKW76BmrZwDbduRP2c8taq9QAgjlVCFPvCD0Vhxbt6_xAEwolBSnviy6wI_XO00TV8trJNKlpM-HtAB4RvQf_0M/s220/mvbSKNwL.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-32637828.post-7484858895341306547</id><published>2024-05-05T11:00:00.001+01:00</published><updated>2024-05-05T11:00:00.239+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Java"/><category scheme="http://www.blogger.com/atom/ns#" term="java22"/><category scheme="http://www.blogger.com/atom/ns#" term="programming"/><title type='text'>Java 22: Statements Before super(...)</title><content type='html'>&lt;p&gt;&lt;a href=&quot;https://www.oracle.com/java/technologies/javase/22-relnote-issues.html&quot;&gt;Java 22&lt;/a&gt; brings forth a new &lt;a href=&quot;https://openjdk.org/jeps/447&quot;&gt;preview language feature&lt;/a&gt;: the ability to include statements before the &lt;code&gt;super()&lt;/code&gt; call in constructors.&lt;/p&gt;

&lt;p&gt;Traditionally, Java constructors have had a strict rule: the &lt;code&gt;super()&lt;/code&gt; call, which invokes the superclass constructor, must always be the first statement in a subclass constructor. This rule, while ensuring proper initialisation order, sometimes led to verbose or convoluted constructor implementations, especially when additional setup was required before invoking the superclass constructor.&lt;/p&gt;

&lt;p&gt;With the introduction of JDK 22, this limitation has been relaxed with the introduction of pre-super statements, which allow you to validate and prepare arguments before the &lt;code&gt;super()&lt;/code&gt; call. This also facilitates fail-fast scenarios, because you can perform rigorous argument validation or exception handling before superclass instantiation.&lt;/p&gt;

&lt;p&gt;Here is an example:&lt;/p&gt;
&lt;pre class=&quot;brush:java; gutter:false;&quot;&gt;
class Shape {
  private final String color;

  Shape(String color) {
    this.color = color;
  }
}

class Rectangle extends Shape {
  private final double length;
  private final double width;

  Rectangle(String color, double length, double width) {
    if (length &amp;lt;= 0 || width &amp;lt;= 0) {
      throw new IllegalArgumentException(&quot;Dimensions must be positive&quot;);
    }
    super(color);
    this.length = length;
    this.width = width;
  }
}
&lt;/pre&gt;

&lt;p&gt;In this example, before invoking the superclass constructor, a pre-super statement validates the dimensions of the rectangle, ensuring they are positive.&lt;/p&gt;
</content><link rel='replies' type='application/atom+xml' href='http://fahdshariff.blogspot.com/feeds/7484858895341306547/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fahdshariff.blogspot.com/2024/05/java-22-statements-before-super.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/32637828/posts/default/7484858895341306547'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/32637828/posts/default/7484858895341306547'/><link rel='alternate' type='text/html' href='http://fahdshariff.blogspot.com/2024/05/java-22-statements-before-super.html' title='Java 22: Statements Before super(...)'/><author><name>Fahd Shariff</name><uri>http://www.blogger.com/profile/00919911016127601294</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyUY9JyEBDYzkRuo6ZcCIH40ft7Uo0CcAZL_NMxtyWnKW76BmrZwDbduRP2c8taq9QAgjlVCFPvCD0Vhxbt6_xAEwolBSnviy6wI_XO00TV8trJNKlpM-HtAB4RvQf_0M/s220/mvbSKNwL.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-32637828.post-6425378566159394611</id><published>2024-05-04T17:02:00.002+01:00</published><updated>2024-05-04T17:02:26.360+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Java"/><category scheme="http://www.blogger.com/atom/ns#" term="java22"/><category scheme="http://www.blogger.com/atom/ns#" term="programming"/><title type='text'>Java 22: Unnamed Variables and Patterns</title><content type='html'>&lt;p&gt;&lt;a href=&quot;https://www.oracle.com/java/technologies/javase/22-relnote-issues.html&quot;&gt;Java 22&lt;/a&gt; introduces &lt;a href=&quot;https://openjdk.org/jeps/456&quot;&gt;Unnamed Variables &amp;amp; Patterns&lt;/a&gt;. Unnamed variables are placeholders denoted by the underscore character (_) that stand in for variable names, particularly in situations where the variable&#39;s identifier is insignificant or redundant. They can be declared in several contexts, including local variable declarations, catch clauses, lambda expressions, and more. By omitting explicit variable names in scenarios where the variable name serves no functional purpose, code becomes more succinct, reducing unnecessary verbosity and aiding readability.&lt;/p&gt;

&lt;p&gt;Here are a few examples of unnamed variables in action:&lt;/p&gt;

&lt;p&gt;&lt;b&gt;For-loop:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;brush:java; gutter:false;&quot;&gt;for (Order _ : orders) {
  doSomething();
}
&lt;/pre&gt;

&lt;p&gt;&lt;b&gt;Assignment statement:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;brush:java; gutter:false;&quot;&gt;Queue&amp;lt;Integer&amp;gt; q = ... // x1, y1, z1, x2, y2, z2, ...
var x = q.remove();
var y = q.remove();
var _ = q.remove();
&lt;/pre&gt;

&lt;p&gt;&lt;b&gt;Lambda expressions:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;brush:java; gutter:false;&quot;&gt;list.stream().mapToInt(_ -&amp;gt; 1).sum();
&lt;/pre&gt;

&lt;p&gt;&lt;b&gt;Exception handling:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;brush:java; gutter:false;&quot;&gt;String s = ...
try {
  int i = Integer.parseInt(s);
} catch (NumberFormatException _) {
  System.out.println(&quot;Invalid number: &quot; + s);
}
&lt;/pre&gt;

&lt;p&gt;&lt;b&gt;Try-with-resources:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;brush:java; gutter:false;&quot;&gt;try (BufferedReader _ = new BufferedReader(...)) {
  System.out.println(&quot;File opened successfully.&quot;);
} catch (IOException _) {
  System.err.println(&quot;An error occurred while opening the file.&quot;);
}
&lt;/pre&gt;

&lt;p&gt;&lt;b&gt;Unnamed pattern variables:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;brush:java; gutter:false;&quot;&gt;switch (shape) {
  case Circle _ -&amp;gt; process(shape, 0);
  case Triangle _ -&amp;gt; process(shape, 3);
  case Rectangle _ -&amp;gt; process(shape, 4);
  case var _ -&amp;gt; System.out.println(&quot;Unknown shape&quot;);
}
&lt;/pre&gt;

&lt;h3&gt;&lt;font color=&quot;#000099&quot;&gt;Unnamed Patterns&lt;/font&gt;&lt;/h3&gt;

&lt;p&gt;Unnamed Patterns provide an elegant solution when you need to match a pattern without extracting specific components. If you have nested data structures, such as records within records, with unnamed patterns, you can focus on extracting the necessary components without cluttering your code with unnecessary variable assignments.&lt;/p&gt;
&lt;pre class=&quot;brush:java; gutter:false;&quot;&gt;record Address(String city, String country) {}
record Person(String name, int age, Address address) {}

if (person instanceof Person(var name, _, Address(var city, _))) {
  System.out.println(name + &quot; lives in &quot; + city);
}
&lt;/pre&gt;

&lt;p&gt;So, the next time you encounter a situation where the variable name seems inconsequential, consider using an unnamed variable to streamline your code.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://fahdshariff.blogspot.com/feeds/6425378566159394611/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fahdshariff.blogspot.com/2024/05/java-22-unnamed-variables-and-patterns.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/32637828/posts/default/6425378566159394611'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/32637828/posts/default/6425378566159394611'/><link rel='alternate' type='text/html' href='http://fahdshariff.blogspot.com/2024/05/java-22-unnamed-variables-and-patterns.html' title='Java 22: Unnamed Variables and Patterns'/><author><name>Fahd Shariff</name><uri>http://www.blogger.com/profile/00919911016127601294</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyUY9JyEBDYzkRuo6ZcCIH40ft7Uo0CcAZL_NMxtyWnKW76BmrZwDbduRP2c8taq9QAgjlVCFPvCD0Vhxbt6_xAEwolBSnviy6wI_XO00TV8trJNKlpM-HtAB4RvQf_0M/s220/mvbSKNwL.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-32637828.post-6845428049933944890</id><published>2024-04-07T16:23:00.001+01:00</published><updated>2024-04-07T16:23:13.815+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="ffmpeg"/><title type='text'>Useful FFmpeg Commands</title><content type='html'>&lt;p&gt;&lt;a href=&quot;https://www.ffmpeg.org/&quot;&gt;FFmpeg&lt;/a&gt; is a great command-line tool for dealing with audio and video files. Here are a couple of useful commands:&lt;/p&gt;

&lt;b&gt;&lt;font color=&quot;#000099&quot;&gt;Extract audio from a video&lt;/font&gt;&lt;/b&gt;
&lt;pre style=&quot;font-family: Consolas,Courier New,Courier,mono,serif; font-size:12px;&quot;&gt;
$ ffmpeg -i video.mp4 -q:a 0 -map a audio.mp3
&lt;/pre&gt;

&lt;b&gt;&lt;font color=&quot;#000099&quot;&gt;Concatenate multiple videos into a single file&lt;/font&gt;&lt;/b&gt;
&lt;p&gt;First, create a file containing the list of videos to concatenate, and then pass it through ffmpeg:&lt;/p&gt;
&lt;pre style=&quot;font-family: Consolas,Courier New,Courier,mono,serif; font-size:12px;&quot;&gt;
$ cat list.txt
file &#39;/path/to/file1.mp4&#39;
file &#39;/path/to/file2.mp4&#39;
file &#39;/path/to/file3.mp4&#39;

$ ffmpeg -safe 0 -f concat -i list.txt -c copy output.mp4
&lt;/pre&gt;

&lt;p&gt;&lt;b&gt;&lt;font color=&quot;#000099&quot;&gt;Related post:&lt;/font&gt;&lt;/b&gt;&lt;br/&gt;
&lt;a href=&quot;https://fahdshariff.blogspot.com/2020/02/ffmpeg-cheatsheet.html&quot;&gt;FFmpeg Cheatsheet&lt;/a&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://fahdshariff.blogspot.com/feeds/6845428049933944890/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fahdshariff.blogspot.com/2024/04/useful-ffmpeg-commands.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/32637828/posts/default/6845428049933944890'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/32637828/posts/default/6845428049933944890'/><link rel='alternate' type='text/html' href='http://fahdshariff.blogspot.com/2024/04/useful-ffmpeg-commands.html' title='Useful FFmpeg Commands'/><author><name>Fahd Shariff</name><uri>http://www.blogger.com/profile/00919911016127601294</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyUY9JyEBDYzkRuo6ZcCIH40ft7Uo0CcAZL_NMxtyWnKW76BmrZwDbduRP2c8taq9QAgjlVCFPvCD0Vhxbt6_xAEwolBSnviy6wI_XO00TV8trJNKlpM-HtAB4RvQf_0M/s220/mvbSKNwL.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-32637828.post-720482594595549347</id><published>2024-01-01T15:31:00.000+00:00</published><updated>2024-01-01T15:31:32.144+00:00</updated><title type='text'>fahd.blog in 2023</title><content type='html'>&lt;p&gt;&lt;b&gt;&lt;font color=&quot;#000099&quot;&gt;Happy 2024, everyone!&lt;/font&gt;&lt;/b&gt;&lt;/p&gt;&lt;p&gt;I&#39;d like to wish everyone a great start to an even greater new year!&lt;/p&gt;

&lt;p&gt;In keeping with tradition, here&#39;s one last look back at &lt;a href=&quot;http://fahdshariff.blogspot.com&quot;&gt;fahd.blog&lt;/a&gt; in 2023.&lt;/p&gt;

&lt;p&gt;During 2023, I posted 11 new entries on &lt;a href=&quot;http://fahdshariff.blogspot.com&quot;&gt;fahd.blog&lt;/a&gt;. I am also thrilled that I have more readers from all over the world! Thanks for reading and especially for giving feedback.&lt;/p&gt;

&lt;b&gt;&lt;font color=&quot;#000099&quot;&gt;Top 3 posts of 2023:&lt;/font&gt;&lt;/b&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://fahdshariff.blogspot.com/2023/04/java-20-record-patterns-in-for-loops.html&quot;&gt;Java 20: Record Patterns in For Loops&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://fahdshariff.blogspot.com/2023/08/matrix-operations-in-kdbq.html&quot;&gt;Matrix Operations in kdb+/q&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://fahdshariff.blogspot.com/2023/09/linear-and-polynomial-regression-in-kdbq.html&quot;&gt;Linear and Polynomial Regression in kdb+/q&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I&#39;m going to be writing a lot more this year, so stay tuned for more great techie tips, tricks and hacks! :)&lt;/p&gt;

&lt;b&gt;&lt;font color=&quot;#000099&quot;&gt;Related posts:&lt;/font&gt;&lt;/b&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://fahdshariff.blogspot.com/2023/01/fahdblog-in-2022.html&quot;&gt;fahd.blog in 2022&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://fahdshariff.blogspot.com/2022/01/fahdblog-in-2021.html&quot;&gt;fahd.blog in 2021&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://fahdshariff.blogspot.com/2021/01/fahdblog-in-2020.html&quot;&gt;fahd.blog in 2020&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://fahdshariff.blogspot.com/2020/01/fahdblog-in-2019.html&quot;&gt;fahd.blog in 2019&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://fahdshariff.blogspot.com/2019/01/fahdblog-in-2018.html&quot;&gt;fahd.blog in 2018&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://fahdshariff.blogspot.com/2018/01/fahdblog-in-2017.html&quot;&gt;fahd.blog in 2017&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://fahdshariff.blogspot.com/2017/01/fahdblog-in-2016.html&quot;&gt;fahd.blog in 2016&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://fahdshariff.blogspot.com/2016/01/fahdblog-in-2015.html&quot;&gt;fahd.blog in 2015&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://fahdshariff.blogspot.com/2015/01/fahdblog-in-2014.html&quot;&gt;fahd.blog in 2014&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://fahdshariff.blogspot.com/2014/01/fahdblog-in-2013.html&quot;&gt;fahd.blog in 2013&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://fahdshariff.blogspot.com/2013/01/fahdblog-in-2012.html&quot;&gt;fahd.blog in 2012&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://fahdshariff.blogspot.com/2012/01/fahdblog-in-2011.html&quot;&gt;fahd.blog in 2011&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://fahdshariff.blogspot.com/2011/01/fahdblog-in-2010.html&quot;&gt;fahd.blog in 2010&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><link rel='replies' type='application/atom+xml' href='http://fahdshariff.blogspot.com/feeds/720482594595549347/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fahdshariff.blogspot.com/2024/01/fahdblog-in-2023.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/32637828/posts/default/720482594595549347'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/32637828/posts/default/720482594595549347'/><link rel='alternate' type='text/html' href='http://fahdshariff.blogspot.com/2024/01/fahdblog-in-2023.html' title='fahd.blog in 2023'/><author><name>Fahd Shariff</name><uri>http://www.blogger.com/profile/00919911016127601294</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyUY9JyEBDYzkRuo6ZcCIH40ft7Uo0CcAZL_NMxtyWnKW76BmrZwDbduRP2c8taq9QAgjlVCFPvCD0Vhxbt6_xAEwolBSnviy6wI_XO00TV8trJNKlpM-HtAB4RvQf_0M/s220/mvbSKNwL.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-32637828.post-4219710114062099145</id><published>2023-12-09T17:29:00.000+00:00</published><updated>2023-12-09T17:29:09.785+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="programming"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><title type='text'>Python: Running Tasks in Parallel</title><content type='html'>&lt;p&gt;The &lt;a href=&quot;https://docs.python.org/3/library/concurrent.futures.html&quot;&gt;&lt;code&gt;concurrent.futures&lt;/code&gt;&lt;/a&gt; module can be used to run tasks in parallel in Python. Here is an example:&lt;/p&gt;

&lt;pre class=&quot;brush:python; gutter:false;&quot;&gt;
import concurrent.futures
from concurrent.futures import ProcessPoolExecutor

with ProcessPoolExecutor(max_workers = 10) as executor:
    futures = [executor.submit(perform_task, task) for task in tasks]
	
results = [future.result() for future in futures]
&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;ProcessPoolExecutor&lt;/code&gt; class uses a pool of processes to execute tasks asynchronously. The &lt;code&gt;submit&lt;/code&gt; function immediately returns a &lt;code&gt;Future&lt;/code&gt; object, and you can call &lt;code&gt;future.result()&lt;/code&gt;, which will block until the task has completed.&lt;/p&gt;

&lt;p&gt;Note that there is also a &lt;code&gt;ThreadPoolExecutor&lt;/code&gt; class which uses a pool of threads; however, due to the &lt;a href=&quot;https://docs.python.org/3/glossary.html#term-global-interpreter-lock&quot;&gt;Global Interpreter Lock&lt;/a&gt;, only one thread can execute python bytecode at any one time, which means that you will not achieve any parallelisation in most cases.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://fahdshariff.blogspot.com/feeds/4219710114062099145/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fahdshariff.blogspot.com/2023/12/python-running-tasks-in-parallel.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/32637828/posts/default/4219710114062099145'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/32637828/posts/default/4219710114062099145'/><link rel='alternate' type='text/html' href='http://fahdshariff.blogspot.com/2023/12/python-running-tasks-in-parallel.html' title='Python: Running Tasks in Parallel'/><author><name>Fahd Shariff</name><uri>http://www.blogger.com/profile/00919911016127601294</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyUY9JyEBDYzkRuo6ZcCIH40ft7Uo0CcAZL_NMxtyWnKW76BmrZwDbduRP2c8taq9QAgjlVCFPvCD0Vhxbt6_xAEwolBSnviy6wI_XO00TV8trJNKlpM-HtAB4RvQf_0M/s220/mvbSKNwL.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-32637828.post-1016180757389172635</id><published>2023-12-03T12:00:00.001+00:00</published><updated>2023-12-03T12:00:00.252+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Java"/><category scheme="http://www.blogger.com/atom/ns#" term="java21"/><category scheme="http://www.blogger.com/atom/ns#" term="programming"/><title type='text'>Java 21: Sequenced Collections</title><content type='html'>&lt;p&gt;Introduced in &lt;a href=&quot;https://www.oracle.com/java/technologies/javase/21-relnote-issues.html&quot;&gt;Java 21&lt;/a&gt;, a &lt;a href=&quot;https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/SequencedCollection.html&quot;&gt;&lt;code&gt;SequencedCollection&lt;/code&gt;&lt;/a&gt; is a &lt;code&gt;Collection&lt;/code&gt; whose elements have a defined encounter order i.e. it has first and last elements, and the elements between them have successors and predecessors. Some examples include &lt;code&gt;List&lt;/code&gt;, &lt;code&gt;Deque&lt;/code&gt;, &lt;code&gt;SortedSet&lt;/code&gt;, and &lt;code&gt;LinkedHashSet&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;SequencedCollection&lt;/code&gt; interface provides methods to add, retrieve, and remove elements at either end of the collection. It also has a &lt;code&gt;reversed()&lt;/code&gt; method which provides a reverse-ordered view of the original collection.

&lt;p&gt;Similarly, the new &lt;a href=&quot;https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/SequencedMap.html&quot;&gt;&lt;code&gt;SequencedMap&lt;/code&gt;&lt;/a&gt; interface is a map that has a well-defined encounter order, supports operations at both ends, and is reversible. Examples include &lt;code&gt;LinkedHashMap&lt;/code&gt; and &lt;code&gt;TreeMap&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Example usage:&lt;/p&gt;

&lt;pre class=&quot;brush:java; gutter:false;&quot;&gt;
var set = new LinkedHashSet&amp;lt;String&amp;gt;(Arrays.asList(&quot;a&quot;, &quot;b&quot;, &quot;c&quot;));

set instanceof SequencedCollection
==&gt; true

set.getFirst()
==&gt; &quot;a&quot;

set.getLast()
==&gt; &quot;c&quot;

set.reversed()
==&gt; [c, b, a]
&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://fahdshariff.blogspot.com/feeds/1016180757389172635/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fahdshariff.blogspot.com/2023/12/java-21-sequenced-collections.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/32637828/posts/default/1016180757389172635'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/32637828/posts/default/1016180757389172635'/><link rel='alternate' type='text/html' href='http://fahdshariff.blogspot.com/2023/12/java-21-sequenced-collections.html' title='Java 21: Sequenced Collections'/><author><name>Fahd Shariff</name><uri>http://www.blogger.com/profile/00919911016127601294</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyUY9JyEBDYzkRuo6ZcCIH40ft7Uo0CcAZL_NMxtyWnKW76BmrZwDbduRP2c8taq9QAgjlVCFPvCD0Vhxbt6_xAEwolBSnviy6wI_XO00TV8trJNKlpM-HtAB4RvQf_0M/s220/mvbSKNwL.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-32637828.post-581202473238324453</id><published>2023-12-02T17:03:00.005+00:00</published><updated>2023-12-02T17:03:59.385+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Java"/><category scheme="http://www.blogger.com/atom/ns#" term="java21"/><category scheme="http://www.blogger.com/atom/ns#" term="programming"/><title type='text'>Java 21: Unnamed Classes</title><content type='html'>&lt;p&gt;&lt;a href=&quot;https://www.oracle.com/java/technologies/javase/21-relnote-issues.html&quot;&gt;Java 21&lt;/a&gt; introduces &lt;a href=&quot;https://openjdk.org/jeps/445&quot;&gt;Unnamed Classes&lt;/a&gt; (a preview language feature) that allow you to write small programs without having an enclosing class declaration.&lt;/p&gt;

&lt;p&gt;Here is the classic Hello World program that we were all taught when starting to learn Java:&lt;/p&gt;

&lt;pre class=&quot;brush:java; gutter:false;&quot;&gt;
public class HelloWorld { 
  public static void main(String[] args) { 
    System.out.println(&quot;Hello, World!&quot;);
  }
}
&lt;/pre&gt;

&lt;p&gt;There is a lot of clutter here. Using an unnamed class, this can be simplified to:&lt;/p&gt;

&lt;pre class=&quot;brush:java; gutter:false;&quot;&gt;
void main() { 
  System.out.println(&quot;Hello, World!&quot;);
}
&lt;/pre&gt;

&lt;p&gt;Not only is the enclosing class not required, but the &lt;code&gt;main&lt;/code&gt; method has also been enhanced so that it does not need to be &lt;code&gt;public&lt;/code&gt;, &lt;code&gt;static&lt;/code&gt; or require any arguments.&lt;/p&gt;

&lt;p&gt;You can also add fields and methods to an unnamed class, as shown below:&lt;/p&gt;
&lt;pre class=&quot;brush:java; gutter:false;&quot;&gt;
private static final String GREETING = &quot;Hello, World!&quot;;

private String getGreeting() {
  return GREETING;
}

void main() { 
  System.out.println(getGreeting());
}
&lt;/pre&gt;

&lt;p&gt;Since an unnamed class cannot be instantiated or referenced by name, it is only useful as a standalone program or as an entry point to a program.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://fahdshariff.blogspot.com/feeds/581202473238324453/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fahdshariff.blogspot.com/2023/12/java-21-unnamed-classes.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/32637828/posts/default/581202473238324453'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/32637828/posts/default/581202473238324453'/><link rel='alternate' type='text/html' href='http://fahdshariff.blogspot.com/2023/12/java-21-unnamed-classes.html' title='Java 21: Unnamed Classes'/><author><name>Fahd Shariff</name><uri>http://www.blogger.com/profile/00919911016127601294</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyUY9JyEBDYzkRuo6ZcCIH40ft7Uo0CcAZL_NMxtyWnKW76BmrZwDbduRP2c8taq9QAgjlVCFPvCD0Vhxbt6_xAEwolBSnviy6wI_XO00TV8trJNKlpM-HtAB4RvQf_0M/s220/mvbSKNwL.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-32637828.post-3462446320284066052</id><published>2023-11-25T18:23:00.001+00:00</published><updated>2023-12-04T21:21:10.148+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Java"/><category scheme="http://www.blogger.com/atom/ns#" term="java21"/><category scheme="http://www.blogger.com/atom/ns#" term="programming"/><title type='text'>Java 21: String Templates</title><content type='html'>&lt;p&gt;In &lt;a href=&quot;https://www.oracle.com/java/technologies/javase/21-relnote-issues.html&quot;&gt;Java 21&lt;/a&gt;, &lt;a href=&quot;https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/lang/StringTemplate.html&quot;&gt;String Templates&lt;/a&gt; have been introduced as a preview language feature, that allow text and expressions to be composed safely and efficiently, without using the &lt;code&gt;+&lt;/code&gt; operator.&lt;/p&gt;

&lt;p&gt;Here is an example:&lt;/p&gt;

&lt;pre class=&quot;brush:java; gutter:false;&quot;&gt;
int x = 5, y = 6;

String s = STR.&quot;\{x} plus \{y} is equal to \{x + y}&quot;;

// evaluates to: &quot;5 plus 6 is equal to 11&quot;
&lt;/pre&gt;

&lt;p&gt;In this example, &lt;code&gt;STR&lt;/code&gt; is a template processor. The template is &lt;code&gt;\{x} plus \{y} is equal to \{x + y}&lt;/code&gt; and &lt;code&gt;\{x}&lt;/code&gt; is one of the embedded expressions in the template. The &lt;a href=&quot;https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/lang/StringTemplate.html#STR&quot;&gt;&lt;code&gt;STR&lt;/code&gt;&lt;/a&gt; template processor is defined in the Java Platform (and is automatically imported into every Java source file), and it performs string interpolation by evaluating the embedded expressions.&lt;/p&gt;

&lt;p&gt;More examples:&lt;/p&gt;

&lt;pre class=&quot;brush:java; gutter:false;&quot;&gt;
// you can invoke methods, access fields, use ternaries
String s = STR.&quot;\{user.name}: Access \{user.hasAccess() ? &quot;Granted&quot; : &quot;Denied&quot;}&quot;;

// multi-line template expression
String xml = STR.&quot;&quot;&quot;
&amp;lt;book&amp;gt;
  &amp;lt;author&amp;gt;\{author}&amp;lt;/author&amp;gt;
  &amp;lt;title&amp;gt;\{title}&amp;lt;/title&amp;gt;
&amp;lt;/book&amp;gt;
&quot;&quot;&quot;;
&lt;/pre&gt;

&lt;p&gt;&lt;b&gt;&lt;font color=&quot;#000099&quot;&gt;FMT Template Processor&lt;/font&gt;&lt;/b&gt;&lt;p&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/FormatProcessor.html#FMT&quot;&gt;FMT&lt;/a&gt; is like STR but it also interprets format specifiers which appear to the left of embedded expressions. For example:&lt;/p&gt;

&lt;pre class=&quot;brush:java; gutter:false;&quot;&gt;
double val = 4999.4567;

FormatProcessor.FMT.&quot;The value is %,.2f\{val}&quot;;

// evaluates to: &quot;The value is 4,999.46&quot;
&lt;/pre&gt;

&lt;p&gt;It&#39;s quite easy to create your own Template Processor by implementing &lt;a href=&quot;https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/lang/StringTemplate.Processor.html&quot;&gt;&lt;code&gt;StringTemplate.Processor&lt;/code&gt;&lt;/a&gt;. This is useful if you want to validate inputs before composing the string. It&#39;s also possible to return an object of any type, not just &lt;code&gt;String&lt;/code&gt;. For instance, a SQL Template processor could first sanitise the input to prevent a SQL injection attack, and then return a &lt;code&gt;PreparedStatement&lt;/code&gt; instead of a &lt;code&gt;String&lt;/code&gt;.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://fahdshariff.blogspot.com/feeds/3462446320284066052/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fahdshariff.blogspot.com/2023/11/java-21-string-templates.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/32637828/posts/default/3462446320284066052'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/32637828/posts/default/3462446320284066052'/><link rel='alternate' type='text/html' href='http://fahdshariff.blogspot.com/2023/11/java-21-string-templates.html' title='Java 21: String Templates'/><author><name>Fahd Shariff</name><uri>http://www.blogger.com/profile/00919911016127601294</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyUY9JyEBDYzkRuo6ZcCIH40ft7Uo0CcAZL_NMxtyWnKW76BmrZwDbduRP2c8taq9QAgjlVCFPvCD0Vhxbt6_xAEwolBSnviy6wI_XO00TV8trJNKlpM-HtAB4RvQf_0M/s220/mvbSKNwL.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-32637828.post-8285463300864076685</id><published>2023-09-03T09:00:00.001+01:00</published><updated>2023-09-03T09:00:00.149+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="kdb"/><category scheme="http://www.blogger.com/atom/ns#" term="programming"/><category scheme="http://www.blogger.com/atom/ns#" term="q"/><category scheme="http://www.blogger.com/atom/ns#" term="regression"/><category scheme="http://www.blogger.com/atom/ns#" term="statistics"/><title type='text'>Linear and Polynomial Regression in kdb+/q</title><content type='html'>&lt;p&gt;In this post, I&#39;ll describe how you can implement &lt;a href=&quot;https://en.wikipedia.org/wiki/Regression_analysis#Linear_regression&quot;&gt;linear&lt;/a&gt; and &lt;a href=&quot;https://en.wikipedia.org/wiki/Polynomial_regression&quot;&gt;polynomial&lt;/a&gt; regression in kdb+/q to determine the equation of a line of best fit (also known as a trendline) through the data on a scatter plot.&lt;/p&gt;

&lt;p&gt;Consider the following scatter plot:&lt;/p&gt;
&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi41qYrwECPZD3k3iuVQQG-3gOKhtNDezSO_rgC-7APUfvQU6U-pWKVu-_Ch4zSO4nm0ujthgAEqcOcmEXn4Zo4npmqyiq5D0flW19sW_mgLDPevkmebEr7K5YDDn4ElazOQ0o-owIsRKwGV8SSmgFINEZDPF7G3MTk5zqLDe82EseggWJOxd8wuQ/s1600/scatterplot.png&quot;/&gt;


&lt;p&gt;Our aim is to estimate a function of a line that most closely fits the data.&lt;/p&gt;

&lt;p&gt;The vector of estimated polynomial regression coefficients (using ordinary least squares estimation) can be obtained using the following formula (for information about how this formula is derived, see &lt;a href=&quot;https://en.wikipedia.org/wiki/Regression_analysis&quot;&gt;Regression analysis [Wikipedia]&lt;/a&gt;):&lt;/p&gt;

&lt;h1&gt;&lt;font color=&quot;green&quot;&gt;&lt;code&gt;
b = (X&lt;sup&gt;T&lt;/sup&gt;X)&lt;sup&gt;−1&lt;/sup&gt;X&lt;sup&gt;T&lt;/sup&gt;y
&lt;/code&gt;&lt;/font&gt;&lt;/h1&gt;

&lt;p&gt;This can be translated into q as follows:&lt;/p&gt;

&lt;pre style=&quot;font-family: Consolas,Courier New,Courier,mono,serif; font-size:12px;background:black;color:white&quot;&gt;
computeRegressionCoefficients:{
    xt:&lt;font color=&quot;00FFFF&quot;&gt;flip&lt;/font&gt; x;
    xt_x:xt &lt;font color=&quot;00FFFF&quot;&gt;mmu&lt;/font&gt; x;
    xt_x_inv:&lt;font color=&quot;00FFFF&quot;&gt;inv&lt;/font&gt; xt_x;
    xt_y:xt &lt;font color=&quot;00FFFF&quot;&gt;mmu&lt;/font&gt; y;
    xt_x_inv &lt;font color=&quot;00FFFF&quot;&gt;mmu&lt;/font&gt; xt_y}
&lt;/pre&gt;

&lt;p&gt;&lt;b&gt;&lt;font color=&quot;#000099&quot;&gt;Linear:&lt;/font&gt;&lt;/b&gt;&lt;br/&gt;
In order to perform linear regression, we have to first create a matrix X with a column of 1s and a column containing the x-values. The output of linear regression will be a vector of 2 coefficients and the equation of the trendline will be of the form: &lt;code&gt;y = b&lt;sub&gt;1&lt;/sub&gt;x + b&lt;sub&gt;0&lt;/sub&gt;&lt;/code&gt;&lt;/p&gt;

&lt;pre style=&quot;font-family: Consolas,Courier New,Courier,mono,serif; font-size:12px;background:black;color:white&quot;&gt;
computeLinearRegressionCoefficients:{
    computeRegressionCoefficients[&lt;font color=&quot;00FFFF&quot;&gt;flip&lt;/font&gt; (1f;x);y]}
&lt;/pre&gt;
&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5Z6hr2zIITyNaexm4Yj6Thj6HGVw4N6A7D3U5gQD3IKgBZ7bCuCPIkCiQIthHugFUMYNrzk6IER9ChHovbuVunDpSoh62iOUgMEhT-iJrYGeINTPomju9qU1Yhl4iWvPTtl61Whaw9I_ckYtHYHzC128mGSj-Uxq5QJ9exSCQXjlzX8zDsFS0dg/s1600/scatterplot_linear.png&quot;/&gt;

&lt;p&gt;&lt;b&gt;&lt;font color=&quot;#000099&quot;&gt;Polynomial:&lt;/font&gt;&lt;/b&gt;&lt;br/&gt;
In order to fit a polynomial line, all we have to do is take the matrix X from the linear regression model and add more columns corresponding to the order of the polynomial desired. For example, for quadratic regression, we will add a column for x&lt;sup&gt;2&lt;/sup&gt; on the right side of the matrix X. The output of quadratic regression will be a vector of 3 coefficients and the equation of the curve will be of the form: &lt;code&gt;y = b&lt;sub&gt;2&lt;/sub&gt;x&lt;sup&gt;2&lt;/sup&gt; + b&lt;sub&gt;1&lt;/sub&gt;x + b&lt;sub&gt;0&lt;/sub&gt;&lt;/code&gt;&lt;/p&gt;
&lt;pre style=&quot;font-family: Consolas,Courier New,Courier,mono,serif; font-size:12px;background:black;color:white&quot;&gt;
&lt;font color=&quot;orange&quot;&gt;// quadratic&lt;/font&gt;
computeQuadraticRegressionCoefficients:{
    computeRegressionCoefficients[&lt;font color=&quot;00FFFF&quot;&gt;flip&lt;/font&gt; (1f;x;x*x);y]}

&lt;font color=&quot;orange&quot;&gt;// cubic&lt;/font&gt;
computeCubicRegressionCoefficients:{
    computeRegressionCoefficients[&lt;font color=&quot;00FFFF&quot;&gt;flip&lt;/font&gt; (1f;x;x*x;x*x*x);y]}

&lt;font color=&quot;orange&quot;&gt;// generalisation of polynomial regression for any order&lt;/font&gt;
computePolynomialRegressionCoefficients:{[x;y;order]
    computeRegressionCoefficients[&lt;font color=&quot;00FFFF&quot;&gt;flip&lt;/font&gt; x &lt;font color=&quot;00FFFF&quot;&gt;xexp&lt;/font&gt;/: &lt;font color=&quot;00FFFF&quot;&gt;til&lt;/font&gt; order+1;y]}
&lt;/pre&gt;

&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwHQrw0PCiHkGlDiVBOW2ezepZbvo7tC7M4-x7spGaQK34Dco5YqHp4fIwODvj-uOI0PStpBb5cXtUlnQP3gFQxG6tuJ10yQQJQH-1W5h_ZlbEUjzA8n1PEisM-Df_DLwGN_DoxRibMeuVh4qqJlfNplZfRKt9gj-10X_rk7kvs8qMsx-Cx87Avw/s1600/scatterplot_quadratic.png&quot;/&gt;

&lt;p&gt;&lt;b&gt;&lt;font color=&quot;#000099&quot;&gt;Related post:&lt;/font&gt;&lt;/b&gt;&lt;br/&gt;
&lt;a href=&quot;https://fahdshariff.blogspot.com/2023/08/matrix-operations-in-kdbq.html&quot;&gt;Matrix Operations in kdb+/q&lt;/a&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://fahdshariff.blogspot.com/feeds/8285463300864076685/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fahdshariff.blogspot.com/2023/09/linear-and-polynomial-regression-in-kdbq.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/32637828/posts/default/8285463300864076685'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/32637828/posts/default/8285463300864076685'/><link rel='alternate' type='text/html' href='http://fahdshariff.blogspot.com/2023/09/linear-and-polynomial-regression-in-kdbq.html' title='Linear and Polynomial Regression in kdb+/q'/><author><name>Fahd Shariff</name><uri>http://www.blogger.com/profile/00919911016127601294</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyUY9JyEBDYzkRuo6ZcCIH40ft7Uo0CcAZL_NMxtyWnKW76BmrZwDbduRP2c8taq9QAgjlVCFPvCD0Vhxbt6_xAEwolBSnviy6wI_XO00TV8trJNKlpM-HtAB4RvQf_0M/s220/mvbSKNwL.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi41qYrwECPZD3k3iuVQQG-3gOKhtNDezSO_rgC-7APUfvQU6U-pWKVu-_Ch4zSO4nm0ujthgAEqcOcmEXn4Zo4npmqyiq5D0flW19sW_mgLDPevkmebEr7K5YDDn4ElazOQ0o-owIsRKwGV8SSmgFINEZDPF7G3MTk5zqLDe82EseggWJOxd8wuQ/s72-c/scatterplot.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-32637828.post-1000681570797783588</id><published>2023-09-02T09:00:00.003+01:00</published><updated>2023-09-02T09:00:00.137+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python"/><title type='text'>Python: Printing the Stdout/Stderr of a Subprocess</title><content type='html'>&lt;p&gt;This is how you can run a subprocess in python and print out its stdout and stderr:&lt;/p&gt;
&lt;pre class=&quot;brush:python; gutter:false;&quot;&gt;
import subprocess

proc = subprocess.Popen([&quot;/path/to/myscript&quot;, &quot;arg1&quot;, &quot;arg2&quot;], 
            stderr=subprocess.STDOUT, stdout=subprocess.PIPE)
for line in proc.stdout:
    print(line.decode().rstrip())
proc.wait()
if proc.returncode != 0:
    print(&quot;Command failed with status:&quot;, proc.returncode)
&lt;/pre&gt;

&lt;p&gt;Check out the &lt;a href=&quot;https://docs.python.org/3/library/subprocess.html&quot;&gt;&lt;code&gt;subprocess&lt;/code&gt;&lt;/a&gt; documentation for more information.&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;&lt;font color=&quot;#000099&quot;&gt;Related post:&lt;/font&gt;&lt;/b&gt;&lt;br/&gt;
&lt;a href=&quot;https://fahdshariff.blogspot.com/2010/09/python-cheat-sheet.html&quot;&gt;Python Cheat Sheet&lt;/a&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://fahdshariff.blogspot.com/feeds/1000681570797783588/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fahdshariff.blogspot.com/2023/09/python-printing-stdoutstderr-of.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/32637828/posts/default/1000681570797783588'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/32637828/posts/default/1000681570797783588'/><link rel='alternate' type='text/html' href='http://fahdshariff.blogspot.com/2023/09/python-printing-stdoutstderr-of.html' title='Python: Printing the Stdout/Stderr of a Subprocess'/><author><name>Fahd Shariff</name><uri>http://www.blogger.com/profile/00919911016127601294</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyUY9JyEBDYzkRuo6ZcCIH40ft7Uo0CcAZL_NMxtyWnKW76BmrZwDbduRP2c8taq9QAgjlVCFPvCD0Vhxbt6_xAEwolBSnviy6wI_XO00TV8trJNKlpM-HtAB4RvQf_0M/s220/mvbSKNwL.jpg'/></author><thr:total>0</thr:total></entry></feed>