<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Julia Community 🟣</title>
    <description>The most recent home feed on Julia Community 🟣.</description>
    <link>https://forem.julialang.org</link>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.julialang.org/rss"/>
    <language>en</language>
    <item>
      <title>DearDiary.jl: A lightweight but powerful machine learning experiment tracking tool for Julia</title>
      <dc:creator>Jose Esparza</dc:creator>
      <pubDate>Tue, 04 Nov 2025 22:53:25 +0000</pubDate>
      <link>https://forem.julialang.org/pebeto/deardiaryjl-a-lightweight-but-powerful-machine-learning-experiment-tracking-tool-for-julia-56ap</link>
      <guid>https://forem.julialang.org/pebeto/deardiaryjl-a-lightweight-but-powerful-machine-learning-experiment-tracking-tool-for-julia-56ap</guid>
      <description>&lt;p&gt;After months of planning, and some weeks of development, the package is finally here and ready for use! As a solution for tracking machine learning experiments in Julia, &lt;a href="https://github.com/pebeto/DearDiary.jl" rel="noopener noreferrer"&gt;DearDiary.jl&lt;/a&gt; aims to be lightweight, easy to use, and flexible enough to adapt to different workflows.&lt;/p&gt;

&lt;h2&gt;
  
  
  Motivation
&lt;/h2&gt;

&lt;p&gt;After the unpleasant experience trying to maintain an interface for the REST API from Python's &lt;a href="https://mlflow.org/" rel="noopener noreferrer"&gt;MLFlow&lt;/a&gt; (&lt;a href="https://github.com/JuliaAI/MLFlowClient.jl" rel="noopener noreferrer"&gt;MLFlowClient.jl&lt;/a&gt;, &lt;a href="https://github.com/JuliaAI/MLJFlow.jl" rel="noopener noreferrer"&gt;MLJFlow.jl&lt;/a&gt;), after finding out that it is poorly documented, incomplete, and has some abandoned or partially implemented features (and they are still adding new ones...); an idea came to my mind: why not write the same API but well designed and documented but in Julia? This package is that idea.&lt;/p&gt;

&lt;h2&gt;
  
  
  Core concepts
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Architecture-first
&lt;/h3&gt;

&lt;p&gt;Unlike the common monolithic architecture found in many Julia packages, my goal was to implement something that can be easily maintained and extended over time, focusing on developer experience and code readability (inspired by &lt;a href="https://www.ted.com/talks/alan_edelman_a_programming_language_to_heal_the_planet_together_julia" rel="noopener noreferrer"&gt;Alan Edelman's TED talk&lt;/a&gt; and &lt;a href="https://github.com/JuliaAI/MLJ.jl" rel="noopener noreferrer"&gt;MLJ.jl&lt;/a&gt; "micro-package" architecture).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/pebeto/DearDiary.jl" rel="noopener noreferrer"&gt;DearDiary.jl&lt;/a&gt; consists of an N-layered architecture, which bring us the possibility of encapsulating different functionalities to allow better collaboration and separation of concerns.&lt;br&gt;
Now it is composed of the following layers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Repository layer: responsible for data storage and retrieval.&lt;/li&gt;
&lt;li&gt;Service layer: handles package logic and data processing.&lt;/li&gt;
&lt;li&gt;Route layer: manages RESTful API endpoints and HTTP requests.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And having the idea of implementing a frontend layer in the future.&lt;/p&gt;

&lt;h3&gt;
  
  
  Simple types
&lt;/h3&gt;

&lt;p&gt;One of the problems I found while working on the integration project was the overuse of  complex types. Imagine a type that has a field that is another type with field that is another type that has a field with an integer. Well, that's real and you can find it if you are curious enough. &lt;br&gt;
&lt;a href="https://github.com/pebeto/DearDiary.jl" rel="noopener noreferrer"&gt;DearDiary.jl&lt;/a&gt; tries to avoid that by keeping types simple and flat, totally immutable, and clear as possible. Never search for complexity when you don't need it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Flexible by design
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/pebeto/DearDiary.jl" rel="noopener noreferrer"&gt;DearDiary.jl&lt;/a&gt; is flexible enough to adapt to different workflows. You can use it as a standalone package, or integrate it with other tools in your ML pipeline, or call it from the "outside world" via its RESTful API.&lt;br&gt;
In the case something is not implemented in the way you want it, you can always modify or extend it, thanks to its modularity.&lt;/p&gt;

&lt;h3&gt;
  
  
  Portability
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/pebeto/DearDiary.jl" rel="noopener noreferrer"&gt;DearDiary.jl&lt;/a&gt; is designed to be portable. You can run it locally, on a server, or in the cloud. Thanks to SQLite as the default storage backend, you can easily move your projects between different environments without worrying about compatibility issues.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; one of the main goals for next releases is to support more storage backends, coming from SQL and NoSQL databases, or cloud storage solutions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;

&lt;p&gt;A &lt;a href="https://pebeto.github.io/DearDiary.jl/dev/tutorial/" rel="noopener noreferrer"&gt;Tutorial&lt;/a&gt; is available in the documentation. It covers installation, and a workflow example with &lt;a href="https://github.com/JuliaAI/MLJ.jl" rel="noopener noreferrer"&gt;MLJ.jl&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Contributing
&lt;/h2&gt;

&lt;p&gt;Contributions are welcome! If you find a bug or have a feature request, please open an issue on the &lt;a href="https://github.com/pebeto/DearDiary.jl" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt;. Pull requests are also encouraged. Please make sure to follow the existing &lt;a href="https://github.com/JuliaDiff/BlueStyle" rel="noopener noreferrer"&gt;code style&lt;/a&gt; and include tests for any new features.&lt;/p&gt;

</description>
      <category>mlops</category>
      <category>tracking</category>
      <category>workflow</category>
      <category>restapi</category>
    </item>
    <item>
      <title>StaticCompiler - Generating small binaries</title>
      <dc:creator>Thomas R</dc:creator>
      <pubDate>Thu, 03 Jul 2025 14:26:54 +0000</pubDate>
      <link>https://forem.julialang.org/thomas008/staticcompiler-generating-small-binaries-mp0</link>
      <guid>https://forem.julialang.org/thomas008/staticcompiler-generating-small-binaries-mp0</guid>
      <description>&lt;p&gt;&lt;strong&gt;Static compilation with help of StaticCompiler&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;StaticCompiler is a tool for generating small binaries from Julia source code. Here I'd like to share some experiences of using StaticCompiler.&lt;/p&gt;

&lt;p&gt;So far StaticCompiler works for julia 1.10.x. Unfortunately it does not work for julia 1.11 and above so far: it seems to force to use an old version of GPUCompiler. It would be great, if one could fix that.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Static Compilation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Static compilation imposes some limitations to the julia code: GC allocations are not allowed. Additionally, the code has to be type-stable. Global variables are only allowed if they are constants. Additionally these constants should be non-composite; e.g. arrays as constants are not possible. Because allocations are also forbidden for return values of functions, these values must be of native types or unmodified structs, unless the respective functions or the function calls are inlined.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;StaticTools provides allocation-free datatypes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;StaticTools is a package that procides statically compilable datatypes for StaticCompiler. For example, strings are implemented as MallocString or StaticString, and can be coded using the string macros &lt;code&gt;m""&lt;/code&gt; and &lt;code&gt;c""&lt;/code&gt;, respectively. Both types ensure 0-terminated strings, just like C strings. A StaticString object has a fixed length. For a representing a MallocString object, memory is being allocated. After declaring a MallocString, the user itself is responsible for freeing the allocated memory.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;function f()&lt;br&gt;
  a = c"anne"&lt;br&gt;
  b = m"mike"&lt;br&gt;
  free(b)&lt;br&gt;
  0&lt;br&gt;
end&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Arrays are represented as &lt;code&gt;MallocVector&lt;/code&gt;, &lt;code&gt;MallocArray&lt;/code&gt;, &lt;code&gt;MallocMatrix&lt;/code&gt;, &lt;code&gt;StackVector&lt;/code&gt; or &lt;code&gt;StackArray&lt;/code&gt;. The functions &lt;code&gt;mfill&lt;/code&gt; and &lt;code&gt;sfill&lt;/code&gt; can be used to initialize a Malloc- or StackVector, respectively. You can also use the constructors themselves, and have an undefined initialization.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;a = mfill(m"", 2)&lt;br&gt;
a[1] = m"anne"&lt;br&gt;
a[2] = m"mike"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;b = MallocVector{MallocString}(undef, 2)&lt;br&gt;
b[1] = m"paul"&lt;br&gt;
b[2] = m"john"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;c = mfill(m"", 2, 3)&lt;br&gt;
c[1, 1] = m"a"&lt;br&gt;
c[1, 2] = m"b"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;d = MallocMatrix{MallocString}(undef, 2, 3)&lt;br&gt;
d[1, 1] = m"a"&lt;br&gt;
d[1, 2] = m"b"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;free(a)&lt;br&gt;
free(b)&lt;br&gt;
free(c)&lt;br&gt;
free(d)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;e = sfill(0,2)&lt;br&gt;
e[1] = 1&lt;br&gt;
e[2] = 2&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;f = StackVector{MallocString}(undef, 2)&lt;br&gt;
f[1] = m"a"&lt;br&gt;
f[2] = m"b"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;g = StackMatrix{MallocString}(undef, 2, 3)&lt;br&gt;
g[1, 1] = m"a"&lt;br&gt;
g[1, 2] = m"b"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;A composite type of a &lt;code&gt;StaticString&lt;/code&gt;, e.g. &lt;code&gt;StackVector{StaticString}(undef, 2)&lt;/code&gt; does not to seem possible.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Tuples&lt;/code&gt;, &lt;code&gt;NamedTuples&lt;/code&gt; and &lt;code&gt;Structs&lt;/code&gt; can be used almost in the usual way.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;function f()&lt;br&gt;
  t = (2, 3.3, m"a")&lt;br&gt;
  a, b, c = t&lt;br&gt;
  printf(c"a: %d\n", a)&lt;br&gt;
  printf(c"b: %g\n", b)&lt;br&gt;
  printf(c"c: %s\n", c)&lt;br&gt;
  n = (x = 1, y = 1)&lt;br&gt;
  printf(c"n.x: %d\n", n.x)&lt;br&gt;
  printf(c"n.y: %d\n", n.y)  &lt;br&gt;
  d = NTuple{3, MallocString}((m"a",m"b",m"c"))&lt;br&gt;
  for i in 1:3&lt;br&gt;
    printf(c"%s\n", d[i])&lt;br&gt;
  end&lt;br&gt;
  0&lt;br&gt;
end&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;struct A&lt;br&gt;
  s :: MallocString&lt;br&gt;
  n :: Int64&lt;br&gt;
end&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;function h()&lt;br&gt;
  a = A(m"a", 1)&lt;br&gt;
  0&lt;br&gt;
end&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;When using mutable structs and calling a function that assignes a &lt;code&gt;MallocString&lt;/code&gt;, you have to inline the called function or the function call.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mutable struct A&lt;br&gt;
  s :: MallocString&lt;br&gt;
  n :: Int64&lt;br&gt;
end&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;function f()&lt;br&gt;
  a = A(m"a", 1)&lt;br&gt;
  a.s = m"b"&lt;br&gt;
  a.n = 2&lt;br&gt;
  g(a)&lt;br&gt;
end&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;@inline function g(a::A)&lt;br&gt;
  a.s = m"c"&lt;br&gt;
  a.n = 3&lt;br&gt;
  b = m"a"&lt;br&gt;
end&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Dictionaries and Unions need heap allocation. Enabling static compilation for them is an open, promising project.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Input and Output&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Printing to stdout can be done with help of &lt;code&gt;print&lt;/code&gt;, &lt;code&gt;println&lt;/code&gt; and &lt;code&gt;printf&lt;/code&gt;, in C matter. Flushing (and a newline) is supplied by &lt;code&gt;putchar()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;a = m"a"&lt;br&gt;
print(c"hello")&lt;br&gt;
println(c"hello")&lt;br&gt;
printf(c"a: %s\n", a)&lt;br&gt;
putchar('\n')&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Here are examples for reading and writing files. The function readline was adapted to Windows (I did a PR for StaticTools).&lt;/p&gt;

&lt;p&gt;&lt;code&gt;fp = fopen(file_name, m"r")&lt;br&gt;
str = readline(fp)&lt;br&gt;
fclose(fp)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;fp = fopen(file_name, m"w")&lt;br&gt;
printf(fp, c"hello")&lt;br&gt;
fclose(fp)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;StaticTools also supplies functions to run system functions, convert strings to numbers, measure time, sleep (adapted for Windows), allocate memory, and load dll’s and apply functions of them.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;StaticTools.system(c"dir")&lt;br&gt;
float =  StaticTools.strtod(c"12.34")[1]&lt;br&gt;
int = StaticTools.strtol(c"12")[1]&lt;br&gt;
t_now = StaticTools.time()&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;StaticTools also provides the symbolcall-macro for calling a symbol via LLVM, and can be used to call further C functions. For example, the system function and the time function mentioned above, would be done with&lt;/p&gt;

&lt;p&gt;&lt;code&gt;function sys(s)&lt;br&gt;
  @symbolcall system(pointer(s)::Ptr{UInt8})::Int&lt;br&gt;
end&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;function time() &lt;br&gt;
  @symbolcall time(C_NULL::Ptr{Nothing})::Int&lt;br&gt;
end&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If you want the time in milliseconds, you can use&lt;/p&gt;

&lt;p&gt;&lt;code&gt;function time_ms() :: Int64&lt;br&gt;
  @symbolcall clock()::Int&lt;br&gt;
end&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;StaticTools provides the function usleep. However, it does not seem to work in Windows. With help of &lt;code&gt;symbolcall&lt;/code&gt; it can be adapted.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;function sleep_win(secs::Real)&lt;br&gt;
  millisecs = round(Int, secs * 1000)&lt;br&gt;
  @symbolcall Sleep(millisecs :: Int) :: Int&lt;br&gt;
end&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Debugging - some guide lines&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When there is an error during compiling, the following error messages are typical:&lt;br&gt;
`&lt;code&gt;f()&lt;/code&gt; did not infer to a concrete type. Got Union{}&lt;code&gt;, an error when linking (&lt;/code&gt;ld.lld: error: undefined symbol&lt;code&gt;), or&lt;/code&gt;clang: error: unable to execute command: program not executable`, or a huge error message regarding the LLVM IR.&lt;/p&gt;

&lt;p&gt;From those error message it is hardly possible to distinguish, whether the error is due to some restriction of the static compilation, or simply due to an program error in the Julia code, much less to debug this code.&lt;/p&gt;

&lt;p&gt;Thus it is a good practice, to:&lt;/p&gt;

&lt;p&gt;Firstly, let run the Julia code without compiling.&lt;br&gt;
    Here you can use your favourite debug and trace tools, e.g. @info and @show. Writing in file seems to disturb the printing on stdout. So you would have to leave out any writing to a file.&lt;/p&gt;

&lt;p&gt;Second, check whether any GC allocations occur.&lt;/p&gt;

&lt;p&gt;You can do this, e.g. with help of the macro &lt;code&gt;@time&lt;/code&gt;, or some tool like Allocations. If allocations occur, identify the code segments that cause allocations, and find allocation-free alternatives.&lt;/p&gt;

&lt;p&gt;Third, compile using compile_executable&lt;br&gt;
    When here an error message occurs, then locate the code part, leading to the compilation error. After that, find altenatives for the error-causing lines of code.&lt;/p&gt;

&lt;p&gt;In general, it is of course helpful to start compiling smaller code pieces, and then getting more and more code to compile.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;StaticCompiler is a great tool to compile StaticCompiler small, stand-alone, executable binaries. The generated binaries are in the range usually between around 90 and 300 kB (e.g. for 1500 lines Julia code I got a binary of 210 KB). In contrast to StaticCompiler, PackageCompiler would produce a system image, taking hundreds of MB.&lt;/p&gt;

&lt;p&gt;StaticTools provides a lot of allocation-free functions and data structures. A few have to be adapted to the respective operating system. Dictionaries and unions cannot be compiled so far. It would be a promising project, to extend StaticTools, implementing allocation-free alternatives of these data structures.&lt;/p&gt;

</description>
      <category>compilation</category>
      <category>static</category>
    </item>
    <item>
      <title>Profile a short-running function</title>
      <dc:creator>Neven</dc:creator>
      <pubDate>Mon, 02 Jun 2025 19:21:59 +0000</pubDate>
      <link>https://forem.julialang.org/nsajko/profile-a-short-running-function-5f8j</link>
      <guid>https://forem.julialang.org/nsajko/profile-a-short-running-function-5f8j</guid>
      <description>&lt;p&gt;Recently I went to profile a short-running function. Several Julia packages, ProfileCanvas.jl being one of them, provide functionality for getting a CPU execution profile, often via a macro called like &lt;code&gt;@profview expr_to_profile&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;One problem that can occur is the run time of one invocation of &lt;code&gt;expr_to_profile&lt;/code&gt; being so short that the profile ends up being useless because not enough samples are collected. Here's a quick-and-dirty hack solution to this problem. Criticize it in the comments below!&lt;/p&gt;

&lt;h2&gt;
  
  
  Example: profiling &lt;code&gt;cos(::Float64)&lt;/code&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight julia"&gt;&lt;code&gt;&lt;span class="s"&gt;"""
    run_in_a_loop(run_workload, get_argument, repeat_count)::Nothing
"""&lt;/span&gt;
&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="nf"&gt; run_in_a_loop&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;run_workload&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;F&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;get_argument&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;G&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;repeat_count&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt; &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="x"&gt;{&lt;/span&gt;&lt;span class="n"&gt;F&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;G&lt;/span&gt;&lt;span class="x"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="n"&gt;∈&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;repeat_count&lt;/span&gt;
        &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_argument&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;@noinline&lt;/span&gt; &lt;span class="n"&gt;run_workload&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;Base&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;donotdelete&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c"&gt;# Example: profile `cos(::Float64)` execution&lt;/span&gt;

&lt;span class="c"&gt;# Use a global to prevent constant folding, but precompute everything&lt;/span&gt;
&lt;span class="c"&gt;# to allow the intended workload to dominate the profiling results.&lt;/span&gt;
&lt;span class="n"&gt;precomputed_arguments&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="kt"&gt;NTuple&lt;/span&gt;&lt;span class="x"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Float64&lt;/span&gt;&lt;span class="x"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rand&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Float64&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="x"&gt;,);&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="nf"&gt; get_argument&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;axs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Base&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OneTo&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;precomputed_arguments&lt;/span&gt;&lt;span class="x"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mod&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;axs&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;precomputed_arguments&lt;/span&gt;&lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c"&gt;# Use a global to prevent unexpected compiler optimization.&lt;/span&gt;
&lt;span class="n"&gt;repeat_count&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1000000&lt;/span&gt;

&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="n"&gt;ProfileCanvas&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nd"&gt;@profview&lt;/span&gt;

&lt;span class="c"&gt;# Get everything compiled. The profile may (?) include compilation&lt;/span&gt;
&lt;span class="c"&gt;# here, so we're not interested in it yet.&lt;/span&gt;
&lt;span class="n"&gt;run_in_a_loop&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cos&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;get_argument&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;repeat_count&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@profview&lt;/span&gt; &lt;span class="n"&gt;run_in_a_loop&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cos&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;get_argument&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;repeat_count&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# Run again to see run-time performance.&lt;/span&gt;
&lt;span class="n"&gt;repeat_count&lt;/span&gt; &lt;span class="o"&gt;*=&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;
&lt;span class="nd"&gt;@profview&lt;/span&gt; &lt;span class="n"&gt;run_in_a_loop&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cos&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;get_argument&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;repeat_count&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's the profile flame graph I ended up with:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://forem.julialang.org/images/9jNXKyQ-oJOOyWPZVE-vpjLoOg7Oi1apQu0T__I38lQ/rt:fit/w:800/g:sm/q:0/mb:500000/ar:1/aHR0cHM6Ly9mb3Jl/bS5qdWxpYWxhbmcu/b3JnL3JlbW90ZWlt/YWdlcy91cGxvYWRz/L2FydGljbGVzL3M1/bnVpbHIxb3ZsM3Fm/NGc0ejE3LnBuZw" class="article-body-image-wrapper"&gt;&lt;img src="https://forem.julialang.org/images/9jNXKyQ-oJOOyWPZVE-vpjLoOg7Oi1apQu0T__I38lQ/rt:fit/w:800/g:sm/q:0/mb:500000/ar:1/aHR0cHM6Ly9mb3Jl/bS5qdWxpYWxhbmcu/b3JnL3JlbW90ZWlt/YWdlcy91cGxvYWRz/L2FydGljbGVzL3M1/bnVpbHIxb3ZsM3Fm/NGc0ejE3LnBuZw" alt="profile flame graph for the example" width="800" height="221"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So about 85% of the samples do end up in &lt;code&gt;cos&lt;/code&gt;, even though a single call of &lt;code&gt;cos(::Float64)&lt;/code&gt; is over very quickly. Not bad!&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;donotdelete&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The secret sauce above is &lt;code&gt;donotdelete&lt;/code&gt;. This is its doc string:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;help?&amp;gt; Base.donotdelete
  │ Warning
  │
  │  The following bindings may be internal; they may change or be removed in future versions:
  │
  │    •  Base.donotdelete

  Base.donotdelete(args...)

  This function prevents dead-code elimination (DCE) of itself and any arguments passed to it, but is
  otherwise the lightest barrier possible. In particular, it is not a GC safepoint, does not model an
  observable heap effect, does not expand to any code itself and may be re-ordered with respect to
  other side effects (though the total number of executions may not change).

  A useful model for this function is that it hashes all memory reachable from args and escapes this
  information through some observable side-channel that does not otherwise impact program behavior. Of
  course that's just a model. The function does nothing and returns nothing.

  This is intended for use in benchmarks that want to guarantee that args are actually computed.
  (Otherwise DCE may see that the result of the benchmark is unused and delete the entire benchmark
  code).

  │ Note
  │
  │  donotdelete does not affect constant folding. For example, in donotdelete(1+1), no add
  │  instruction needs to be executed at runtime and the code is semantically equivalent to
  │  donotdelete(2).

  │ Note
  │
  │  This intrinsic does not affect the semantics of code that is dead because it is
  │  unreachable. For example, the body of the function f(x) = false &amp;amp;&amp;amp; donotdelete(x) may be
  │  deleted in its entirety. The semantics of this intrinsic only guarantee that if the
  │  intrinsic is semantically executed, then there is some program state at which the value of
  │  the arguments of this intrinsic were available (in a register, in memory, etc.).

  │ Julia 1.8
  │
  │  This method was added in Julia 1.8.

  Examples
  ≡≡≡≡≡≡≡≡

  function loop()
      for i = 1:1000
          # The compiler must guarantee that there are 1000 program points (in the correct
          # order) at which the value of `i` is in a register, but has otherwise
          # total control over the program.
          donotdelete(i)
      end
  end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Similar functionality in Rust:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://doc.rust-lang.org/beta/std/hint/fn.black_box.html" rel="noopener noreferrer"&gt;https://doc.rust-lang.org/beta/std/hint/fn.black_box.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some C++ libraries offer similar functionality, too. For example, the &lt;a href="https://github.com/facebook/folly" rel="noopener noreferrer"&gt;folly&lt;/a&gt; library has &lt;code&gt;doNotOptimizeAway&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;EDIT: &lt;code&gt;Base.donotdelete&lt;/code&gt; is now a public interface:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/JuliaLang/julia/pull/55774" rel="noopener noreferrer"&gt;https://github.com/JuliaLang/julia/pull/55774&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>Julia expertise needed at the University of Glasgow</title>
      <dc:creator>Eric Silverman</dc:creator>
      <pubDate>Fri, 16 May 2025 09:57:03 +0000</pubDate>
      <link>https://forem.julialang.org/thorsilver/julia-expertise-needed-at-the-university-of-glasgow-2mpm</link>
      <guid>https://forem.julialang.org/thorsilver/julia-expertise-needed-at-the-university-of-glasgow-2mpm</guid>
      <description>&lt;p&gt;Hi everyone!  I'm running a 5-year research project on computational modelling for public health, during which I'll be using an agent-based modelling framework developed previously in Julia.  I'm looking for someone to join me as a Research Associate for the duration, to work alongside me to build out this framework and use it to help Scotland develop improved public health policies.&lt;/p&gt;

&lt;p&gt;Please note that Julia experience and a PhD are required for this position.  You can apply here: &lt;a href="https://www.jobs.gla.ac.uk/job/research-associate-46?source=gla.ac.uk" rel="noopener noreferrer"&gt;https://www.jobs.gla.ac.uk/job/research-associate-46?source=gla.ac.uk&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you have any questions, please contact me anytime: &lt;a href="https://www.gla.ac.uk/schools/healthwellbeing/staff/ericsilverman/" rel="noopener noreferrer"&gt;https://www.gla.ac.uk/schools/healthwellbeing/staff/ericsilverman/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>job</category>
      <category>news</category>
    </item>
    <item>
      <title>Convex hull of a Cartesian product</title>
      <dc:creator>WalterMadelim</dc:creator>
      <pubDate>Fri, 16 May 2025 02:43:45 +0000</pubDate>
      <link>https://forem.julialang.org/waltermadelim/convex-hull-of-a-cartesian-product-358i</link>
      <guid>https://forem.julialang.org/waltermadelim/convex-hull-of-a-cartesian-product-358i</guid>
      <description>&lt;p&gt;I find that this proposition is hardly found in textbooks. And its proof is not easily found on the internet (including asking ChatGPT). Therefore I write it down here as a reference.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight julia"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="nf"&gt; co&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="kt"&gt;Set&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;convex_hull&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Proposition1&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt;   &lt;span class="n"&gt;co&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt; &lt;span class="n"&gt;×&lt;/span&gt; &lt;span class="n"&gt;co&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Y&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;co&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt; &lt;span class="n"&gt;×&lt;/span&gt; &lt;span class="n"&gt;Y&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt; &lt;span class="c"&gt;# "×" is the times---Cartesian Product symbol&lt;/span&gt;
&lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Corollary&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt;  &lt;span class="n"&gt;⨉_i&lt;/span&gt; &lt;span class="n"&gt;co&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;S_i&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;co&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;⨉_i&lt;/span&gt; &lt;span class="n"&gt;S_i&lt;/span&gt;&lt;span class="x"&gt;),&lt;/span&gt; &lt;span class="c"&gt;# "⨉" is the bigtimes---Cartesian Product symbol&lt;/span&gt;

&lt;span class="n"&gt;Proof&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="n"&gt;Assume&lt;/span&gt; &lt;span class="n"&gt;there&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;point&lt;/span&gt; &lt;span class="n"&gt;denoted&lt;/span&gt; &lt;span class="n"&gt;by&lt;/span&gt; &lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt; &lt;span class="n"&gt;∈&lt;/span&gt; &lt;span class="n"&gt;co&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt; &lt;span class="n"&gt;×&lt;/span&gt; &lt;span class="n"&gt;co&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Y&lt;/span&gt;&lt;span class="x"&gt;),&lt;/span&gt; &lt;span class="k"&gt;where&lt;/span&gt;
&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="n"&gt;∈&lt;/span&gt; &lt;span class="n"&gt;co&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt; &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_p&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;_x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;p_&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;x_&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;some&lt;/span&gt;
&lt;span class="n"&gt;_x&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x_&lt;/span&gt; &lt;span class="n"&gt;∈&lt;/span&gt; &lt;span class="n"&gt;X&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="n"&gt;_p&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p_&lt;/span&gt; &lt;span class="o"&gt;≥&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="n"&gt;_p&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;p_&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="x"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="n"&gt;∈&lt;/span&gt; &lt;span class="n"&gt;co&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Y&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt; &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_q&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;_y&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;q_&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;y_&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;some&lt;/span&gt;
&lt;span class="n"&gt;_y&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y_&lt;/span&gt; &lt;span class="n"&gt;∈&lt;/span&gt; &lt;span class="n"&gt;Y&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="n"&gt;_q&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;q_&lt;/span&gt; &lt;span class="o"&gt;≥&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="n"&gt;_q&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;q_&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="x"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;We&lt;/span&gt; &lt;span class="n"&gt;need&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;prove&lt;/span&gt; &lt;span class="n"&gt;that&lt;/span&gt; &lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt; &lt;span class="n"&gt;∈&lt;/span&gt; &lt;span class="n"&gt;co&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt; &lt;span class="n"&gt;×&lt;/span&gt; &lt;span class="n"&gt;Y&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="n"&gt;Indeed&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;there&lt;/span&gt; &lt;span class="n"&gt;are&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="n"&gt;points&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;X&lt;/span&gt; &lt;span class="n"&gt;×&lt;/span&gt; &lt;span class="n"&gt;Y&lt;/span&gt; &lt;span class="n"&gt;as&lt;/span&gt; &lt;span class="n"&gt;follows&lt;/span&gt;
&lt;span class="c"&gt;# point =&amp;gt; its coefficient in a convex combination&lt;/span&gt;
&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_x&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_y&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_p&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;_q&lt;/span&gt; 
&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_x&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y_&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_p&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;q_&lt;/span&gt;
&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x_&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_y&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;p_&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;_q&lt;/span&gt;
&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x_&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y_&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;p_&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;q_&lt;/span&gt;
&lt;span class="n"&gt;such&lt;/span&gt; &lt;span class="n"&gt;that&lt;/span&gt; &lt;span class="n"&gt;their&lt;/span&gt; &lt;span class="n"&gt;convex&lt;/span&gt; &lt;span class="n"&gt;combination&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt; &lt;span class="n"&gt;precisely&lt;/span&gt; &lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="n"&gt;Therefore&lt;/span&gt; &lt;span class="n"&gt;we&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="n"&gt;ve&lt;/span&gt; &lt;span class="n"&gt;proved&lt;/span&gt; &lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt; &lt;span class="n"&gt;∈&lt;/span&gt; &lt;span class="n"&gt;co&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt; &lt;span class="n"&gt;×&lt;/span&gt; &lt;span class="n"&gt;Y&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="n"&gt;The&lt;/span&gt; &lt;span class="n"&gt;reverse&lt;/span&gt; &lt;span class="n"&gt;direction&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt; &lt;span class="n"&gt;easier&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hence&lt;/span&gt; &lt;span class="n"&gt;omitted&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="n"&gt;Therefore&lt;/span&gt; &lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Proposition1&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt; &lt;span class="n"&gt;holds&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="n"&gt;Furthermore&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;co&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt; &lt;span class="n"&gt;×&lt;/span&gt; &lt;span class="n"&gt;co&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Y&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt; &lt;span class="n"&gt;×&lt;/span&gt; &lt;span class="n"&gt;co&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;co&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt; &lt;span class="n"&gt;×&lt;/span&gt; &lt;span class="n"&gt;Y&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt; &lt;span class="n"&gt;×&lt;/span&gt; &lt;span class="n"&gt;co&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;co&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt; &lt;span class="n"&gt;×&lt;/span&gt; &lt;span class="n"&gt;Y&lt;/span&gt; &lt;span class="n"&gt;×&lt;/span&gt; &lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="n"&gt;Likewise&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;we&lt;/span&gt; &lt;span class="n"&gt;conclude&lt;/span&gt; &lt;span class="n"&gt;that&lt;/span&gt; &lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Corollary&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt; &lt;span class="n"&gt;holds&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>launch</category>
    </item>
    <item>
      <title>NeoVim config to use as an IDE for Julia</title>
      <dc:creator>Arash</dc:creator>
      <pubDate>Wed, 12 Feb 2025 19:12:20 +0000</pubDate>
      <link>https://forem.julialang.org/arashshakeri/neovim-config-to-use-as-an-ide-for-julia-4i38</link>
      <guid>https://forem.julialang.org/arashshakeri/neovim-config-to-use-as-an-ide-for-julia-4i38</guid>
      <description>&lt;p&gt;Hello Julia community. i modified my nVim to use as my IDE because i though vscode is too boring and zed is still under development. I shared it on Github so i hope you like it. Just if you have some nVim config before take care and get backup before changing. It is working on Arch linux right now. so I would like to give me some response if its working fluently.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://forem.julialang.orgurl"&gt;https://github.com/arashshakeri/NeoJulia&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://forem.julialang.org/images/SvlHao4ft-5sppLF0PyNOdjE-Gor4pZuvuVhEQDEV1A/rt:fit/w:800/g:sm/q:0/mb:500000/ar:1/aHR0cHM6Ly9mb3Jl/bS5qdWxpYWxhbmcu/b3JnL3JlbW90ZWlt/YWdlcy91cGxvYWRz/L2FydGljbGVzL3pj/cmZ3dzE0OG03MDcx/b2t1dWsxLnBuZw" class="article-body-image-wrapper"&gt;&lt;img src="https://forem.julialang.org/images/SvlHao4ft-5sppLF0PyNOdjE-Gor4pZuvuVhEQDEV1A/rt:fit/w:800/g:sm/q:0/mb:500000/ar:1/aHR0cHM6Ly9mb3Jl/bS5qdWxpYWxhbmcu/b3JnL3JlbW90ZWlt/YWdlcy91cGxvYWRz/L2FydGljbGVzL3pj/cmZ3dzE0OG03MDcx/b2t1dWsxLnBuZw" alt="Image description" width="800" height="401"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ide</category>
      <category>vim</category>
      <category>launch</category>
    </item>
    <item>
      <title>Generate Prime Pairs for Goldbach's Conjecture</title>
      <dc:creator>Jabari Zakiya</dc:creator>
      <pubDate>Fri, 07 Feb 2025 23:48:50 +0000</pubDate>
      <link>https://forem.julialang.org/jzakiya/generate-prime-pairs-for-goldbachs-conjecture-45mk</link>
      <guid>https://forem.julialang.org/jzakiya/generate-prime-pairs-for-goldbachs-conjecture-45mk</guid>
      <description>&lt;p&gt;Hi.&lt;/p&gt;

&lt;p&gt;This is my first program of any substance done in Julia.&lt;br&gt;
It was told Julia is easy to program in, and fast, so I gave it a try.&lt;/p&gt;

&lt;p&gt;The code works (gives correct results) but I'm looking for help to improve it.&lt;br&gt;
It generates all the prime pairs that sum to any even integer n.&lt;/p&gt;

&lt;p&gt;If you want an explanation of hows|whys it works read my just released paper.&lt;/p&gt;

&lt;p&gt;Proof of Goldbach's Conjecture and Bertrand's Postulate Using Prime Genrator Theory(GPT)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.academia.edu/127404211/Proof_of_Goldbachs_Conjecture_and_Bertrands_Postulate_Using_Prime_Generator_Theory_PGT_" rel="noopener noreferrer"&gt;https://www.academia.edu/127404211/Proof_of_Goldbachs_Conjecture_and_Bertrands_Postulate_Using_Prime_Generator_Theory_PGT_&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here's the Ruby code from the paper, which is much faster than my Julia code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Enable YJIT if using CRuby &amp;gt;= 3.3"
RubyVM::YJIT.enable if RUBY_ENGINE == "ruby" and RUBY_VERSION.to_f &amp;gt;= 3.3

def prime_pairs_lohi(n)
  return puts "Input not even n &amp;gt; 2" unless n.even? &amp;amp;&amp;amp; n &amp;gt; 2
  return (pp [n, 1]; pp [n/2, n/2]; pp [n/2, n/2]) if n &amp;lt;= 6

  # generate the low-half-residues (lhr) r &amp;lt; n/2
  lhr = 3.step(n/2, 2).select { |r| r if r.gcd(n) == 1 }
  ndiv2, rhi = n/2, n-2            # lhr:hhr midpoint, max residue limit
  lhr_mults = []                   # for lhr values not part of a pcp

  # store all the powers of the lhr members &amp;lt; n-2
  lhr.each do |r|                  # step thru the lhr members
    r_pwr = r                      # set to first power of r
    break if r &amp;gt; rhi / r_pwr       # exit if r^2 &amp;gt; n-2, as all others are too
    while    r &amp;lt; rhi / r_pwr       # while r^e &amp;lt; n-2
      lhr_mults &amp;lt;&amp;lt; (r_pwr *= r)    # store its current power of r
    end
  end

  # store all the cross-products of the lhr members &amp;lt; n-2
  lhr_dup = lhr.dup                # make copy of the lhr members list
  while (r = lhr_dup.shift) &amp;amp;&amp;amp; !lhr_dup.empty? # do mults of 1st list r w/others
    ri_max = rhi / r               # ri can't multiply r with values &amp;gt; this
    break if lhr_dup[0] &amp;gt; ri_max   # exit if product of consecutive r’s &amp;gt; n-2
    lhr_dup.each do |ri|           # for each residue in reduced list
      break if ri &amp;gt; ri_max         # exit for r if cross-product with ri &amp;gt; n-2
      lhr_mults &amp;lt;&amp;lt; r * ri          # store value if &amp;lt; n-2
    end                            # check cross-products of next lhr member
  end

  # convert lhr_mults vals &amp;gt; n/2 to their lhr complements n-r,
  # store them, those &amp;lt; n/2, in lhr_del; it now holds non-pcp lhr vals
  lhr_del = lhr_mults.map { |r_del| (r_del &amp;gt; ndiv2 ? n - r_del : r_del) }

  pp [n, (lhr -= lhr_del).size]    # show n and pcp prime pairs count
  pp [lhr.first, n-lhr.first]      # show first pcp prime pair of n
  pp [lhr.last,  n-lhr.last]       # show last  pcp prime pair of n
end

def tm; t = Time.now; yield; Time.now - t end  # to time runtime execution

n = ARGV[0].to_i                   # get n value from terminal
puts tm { prime_pairs_lohi(n) }    # show execution runtime as last output
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's my Julia (functional) translation.&lt;br&gt;
I know there's gotta be a faster, more elegant, idomatic way to do it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function prime_pairs_lohi(n)
  if (n&amp;amp;1 == 1 || n &amp;lt; 4) return println("Input not even n &amp;gt; 2") end
  if (n &amp;lt;= 6) println([n, 1]); println([div(n,2),div(n,2)]); println([div(n,2),div(n,2)]); return end

  # generate the low-half-residues (lhr) r &amp;lt; n/2
  ndiv2, rhi = div(n,2), n-2         # lhr:hhr midpoint, max residue limit
  lhr = []                           # array for low half residues
  for r in 3:2:ndiv2; if (gcd(r, n) == 1) append!(lhr, r) end end
  lhr_mults = []                     # for lhr values not part of a pcp

  # store all the powers of the lhr members &amp;lt; n-2
  for r in lhr                       # step thru the lhr members
    r_pwr = r                        # set to first power of r
    if (r &amp;gt; div(rhi, r_pwr)) break end # exit if r^2 &amp;gt; n-2, as all others are too
    while (r &amp;lt; div(rhi, r_pwr))      # while r^e &amp;lt; n-2
      r_pwr *= r                     # increase power of r
      append!(lhr_mults, r_pwr)      # store its current power of r
    end
  end

  # store all the cross-products of the lhr members &amp;lt; n-2
  i = 1; ln = length(lhr)
  while (i &amp;lt; ln)
    r = lhr[i]
    rmax = div(rhi, r)               # ri can't multiply r with values &amp;gt; this
    if (lhr[i+1] &amp;gt; rmax) break end   # exit if product of consecutive r’s &amp;gt; n-2
    j = i+1
    while (j &amp;lt; ln)                   # for each residue in reduced list
      ri = lhr[j]
      if (ri &amp;gt; rmax) break end       # exit for r if cross-product with ri &amp;gt; n-2
      append!(lhr_mults, r * ri)     # store value if &amp;lt; n-2
      j += 1
    end
    i += 1
  end

  # convert lhr_mults vals &amp;gt; n/2 to their lhr complements n-r,
  # store them, those &amp;lt; n/2, in lhr_del; it now holds non-pcp lhr vals
  lhr_del = []
  for r in lhr_mults
    r_del = (r &amp;gt; ndiv2) ? n - r : r
    append!(lhr_del, r_del)
  end

  lhr = setdiff(lhr,lhr_del)         # remove lhr_del residues from lhr

  println([n,  length(lhr)])         # show n and pcp prime pairs count
  println([first(lhr),n-first(lhr)]) # show first pcp prime pair of n
  println([last(lhr), n-last(lhr)])  # show last  pcp prime pair of n
end


num = readline()                     # get n value from terminal
n = parse(Int64, num)
prime_pairs_lohi(n)                  # show execution runtime as last output
println()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It computes correct answers but:&lt;br&gt;
1) It's slower than the Ruby version.&lt;br&gt;
2) Taking input directly from the cli isn't the same as Ruby&lt;br&gt;
3) It doesn't take input numbers using underscores: 123_456_780&lt;br&gt;
4) It needs internal timer like Ruby&lt;/p&gt;

&lt;p&gt;Here a timing difference example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;➜  ~ ruby prime_pairs_lohi.rb 100_000_000
[100000000, 291400]
[11, 99999989]
[49999757, 50000243]
24.21507651

➜  ~ time julia prime_pairs_lohi.jl
100000000
[100000000, 291400]
[11, 99999989]
[49999757, 50000243]

julia prime_pairs_lohi.jl  39.54s user 3.68s system 87% cpu 49.275 total
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So I'm asking help to improve performance and make entering numbers the same as Ruby.&lt;br&gt;
I used the latest Julia 1.11.3 and Ruby 3.4.1 w/YJIT&lt;/p&gt;

</description>
    </item>
    <item>
      <title>🌟 Excited to Share: Introducing AXE Lang! 🌟</title>
      <dc:creator>Sahith Karra</dc:creator>
      <pubDate>Tue, 07 Jan 2025 21:13:26 +0000</pubDate>
      <link>https://forem.julialang.org/sahkar/excited-to-share-introducing-axe-lang-fgn</link>
      <guid>https://forem.julialang.org/sahkar/excited-to-share-introducing-axe-lang-fgn</guid>
      <description>&lt;p&gt;Hi everyone! I’m thrilled to announce my latest project: AXE Lang, an expressive functional programming language hosted in Julia, designed for rapid development and educational use&lt;/p&gt;

&lt;p&gt;This journey began in CSC 430: Programming Languages, where I explored the fascinating world of parsers and interpreters, ultimately implementing my first programming language. That class ignited a passion for understanding how languages work at their core.&lt;br&gt;
Recently, I took this knowledge further, synthesizing key concepts from the course and building my own language from scratch. By hosting AXE Lang in Julia, I was able to combine Julia’s high-performance features with the flexibility and elegance of functional programming. Here are some of my key takeaways from developing AXE. &lt;/p&gt;

&lt;p&gt;💻 The Power of Function Programming&lt;br&gt;
Working with various function programming languages while designing AXE deepened my appreciation for functional paradigms. I found these languages expressive and incredibly fun to work with and urge every programming student to explore this side of programming. &lt;/p&gt;

&lt;p&gt;♻️ Iterative Design&lt;br&gt;
Building a language taught me that iteration was key. It took my multiple iterations in hosting languages before I landed on Julia as the best bet to host my programming language. Additionally, iterating on the syntax and grammar of my language taught me to balance expressiveness with simplicity. For example, I decided to remove the concept of named functions and opted for anonymous functions (lambdas) in my language to promote simplicity and expressiveness, reducing the syntactic overhead.&lt;/p&gt;

&lt;p&gt;🏔️ Development Challenges&lt;br&gt;
Some of the hardest parts of this project was developing the interpreter for a function application where concepts such as lexical scoping and environment management became paramount. These concerns were only heightened after the implementation of mutation in the language, which would introduce side effects to my language. You can read more the strategies while developing this language in the GitHub linked below. &lt;/p&gt;

&lt;p&gt;⏭️ Next Steps with AXE&lt;br&gt;
&lt;a href="https://github.com/sahkar/axe-lang" rel="noopener noreferrer"&gt;https://github.com/sahkar/axe-lang&lt;/a&gt;&lt;br&gt;
If you are interested in AXE Lang, please clone this GitHub repository which provides access to AXE's source code as well as a local interactive REPL to learn AXE syntax and features. &lt;/p&gt;

&lt;p&gt;Please reach out if you have any questions about AXE, Julia, or anything else. Enjoy!&lt;/p&gt;

</description>
      <category>launch</category>
      <category>julia</category>
      <category>prog</category>
    </item>
    <item>
      <title>Categorical Encoding in Julia</title>
      <dc:creator>Essam</dc:creator>
      <pubDate>Fri, 23 Aug 2024 23:38:46 +0000</pubDate>
      <link>https://forem.julialang.org/essamwisam/categorical-encoding-in-julia-2fcb</link>
      <guid>https://forem.julialang.org/essamwisam/categorical-encoding-in-julia-2fcb</guid>
      <description>&lt;p&gt;In this post, I will introduce the Google Summer of Code project that I have been involved in with my mentor &lt;a class="mentioned-user" href="https://forem.julialang.org/ablaom"&gt;@ablaom&lt;/a&gt; for the past three months. It's a new package &lt;a href="https://github.com/JuliaAI/MLJTransforms.jl" rel="noopener noreferrer"&gt;MLJTransforms.jl&lt;/a&gt; which makes five major contributions:&lt;/p&gt;

&lt;h3&gt;
  
  
  ➊ Introducing Contrast Categorical Methods to MLJ
&lt;/h3&gt;

&lt;p&gt;These include &lt;strong&gt;Dummy Coding&lt;/strong&gt;, &lt;strong&gt;Sum Coding&lt;/strong&gt;, &lt;strong&gt;Backward/Forward Difference Coding&lt;/strong&gt;, &lt;strong&gt;Helmert Coding&lt;/strong&gt; as well as generic &lt;strong&gt;Contrast/Hypothesis Coding&lt;/strong&gt;. It's even easily possible to apply different encoding techniques to different columns of an input table!&lt;/p&gt;

&lt;p&gt;These are provided via the &lt;code&gt;ContrastEncoder&lt;/code&gt; construct implemented in the &lt;code&gt;MLJTransforms.jl&lt;/code&gt; package. The motivation behind grouping them is that they can all be viewed as a special case of &lt;strong&gt;Hypothesis Coding&lt;/strong&gt;; the difference from one encoding method to the other is in the hypothesis that the method could be viewed to be testing. &lt;/p&gt;

&lt;h3&gt;
  
  
  ➋ Introducing Other Well Known Categorical Encoding Methods
&lt;/h3&gt;

&lt;p&gt;This includes simpler ones such as &lt;strong&gt;Ordinal&lt;/strong&gt; and &lt;strong&gt;Frequency Encoding&lt;/strong&gt; as well as more sophisticated methods such as &lt;strong&gt;Target Encoding&lt;/strong&gt;. Target encoding supports both binary and multiclass targets and allows regularization to avoid overfitting. It's one of the most renowned and effective methods for categorical encoding.&lt;/p&gt;

&lt;p&gt;These are provided via the &lt;code&gt;OrdinalEncoder&lt;/code&gt;, &lt;code&gt;FrequencyEncoder&lt;/code&gt; and &lt;code&gt;TargetEncoder&lt;/code&gt; constructs implemented in the &lt;code&gt;MLJTransformers.jl&lt;/code&gt; package.&lt;/p&gt;

&lt;p&gt;Prior to this, MLJ only natively supported the &lt;code&gt;OneHotEncoder&lt;/code&gt; for categorical encoding.&lt;/p&gt;

&lt;h3&gt;
  
  
  ➌ Introducing Utility Transformers and Encoders
&lt;/h3&gt;

&lt;p&gt;Many machine learning settings can benefit from treating missing values as an extra category for categorical variables. For this, I implemented a &lt;strong&gt;Missingness Encoder&lt;/strong&gt; that can help fill the missing values for the three major data types of categorical variables. It's even quite useful to cascade this with other categorical encoders that may not be able to deal with missingness.&lt;/p&gt;

&lt;p&gt;Another issue that often comes up when dealing with categorical features is that when their cardinality is high, a classification model may easily overfit; if 100% of the three examples having category "A" belong to class "X" have then might as well predict "X" whenever the category "A". For this, a &lt;strong&gt;CardinalityReducer&lt;/strong&gt; was implemented to group categories that can be regarded as infrequent.&lt;/p&gt;

&lt;p&gt;These are implemented in the &lt;code&gt;MissingnessEncoder&lt;/code&gt; and &lt;code&gt;CardinalityReducer&lt;/code&gt; constructs in the &lt;code&gt;MLJTransforms.jl&lt;/code&gt; package.&lt;/p&gt;

&lt;h3&gt;
  
  
  ➍ Porting Encoders and Transformers from MLJModels.jl
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;MLJModels.jl&lt;/code&gt; already housed a number of transformers as well as a nicely implemented &lt;code&gt;OneHotEncoder&lt;/code&gt;. These were ported to &lt;code&gt;MLJTransforms.jl&lt;/code&gt; so that all encoder/transformers are in the same package.&lt;/p&gt;

&lt;h3&gt;
  
  
  ➎ Introducing the EntityEmbedder
&lt;/h3&gt;

&lt;p&gt;The scope of the summer project originally required only implementing this. Indeed, it proved to be more challenging than other models I implemented in this project. Entity embedding is newer deep learning approach for categorical encoding introduced in 2016 by Cheng Guo and Felix Berkhahn. It employs a set of embedding layers to map each categorical feature into a dense continuous vector in a similar fashion to how they are employed in NLP architectures.&lt;/p&gt;

&lt;p&gt;Consequently, the &lt;code&gt;NeuralNetworkClassifier&lt;/code&gt;, &lt;code&gt;NeuralNetworkRegressor&lt;/code&gt; and the &lt;code&gt;MultitargetNeuralNetworkRegressor&lt;/code&gt; can be trained and evaluated with heterogenous data (i.e., containing categorical features). Moreover, they now offer a &lt;code&gt;transform&lt;/code&gt; which encode the categorical features with the learnt embeddings to be used by an upstream machine learning model.&lt;/p&gt;

&lt;p&gt;To see what it did take to implement this, see the corresponding &lt;a href="https://github.com/FluxML/MLJFlux.jl/pull/267" rel="noopener noreferrer"&gt;PR&lt;/a&gt; where I also mentioned the implementation plan I followed.&lt;/p&gt;

&lt;h3&gt;
  
  
  ➕📕 Documentation !
&lt;/h3&gt;

&lt;p&gt;Although my work extended beyond the original scope of the summer project, I considered it worthwhile to contribute further, knowing it could benefit others in the future. With this in mind, I carefully built and organized the &lt;a href="https://juliaai.github.io/MLJTransforms.jl/dev/" rel="noopener noreferrer"&gt;documentation page&lt;/a&gt;&lt;br&gt;
, creating a taxonomy for the methods I implemented, adding four tutorials to help users learn about categorical encoding techniques, and streamlining the process for other developers to contribute to the codebase.&lt;br&gt;
Do you like the work? See the Imbalance project I worked on last year as well &lt;a href="https://forem.julialang.org/essamwisam/class-imbalance-in-julia-3jek"&gt;here&lt;/a&gt;. Thank you!&lt;/p&gt;

&lt;h3&gt;
  
  
  🎁 Final Bonus
&lt;/h3&gt;

&lt;p&gt;In the community bonding period, I took some time to expose and revamp documentation for &lt;a href="https://github.com/FluxML/MLJFlux.jl" rel="noopener noreferrer"&gt;MLJFlux.jl&lt;/a&gt;. This included preparing seven workflow examples to present various features of the package as well as a novel tutorial on how to use RNNs for sequence classification via the package. See that and more &lt;a href="https://github.com/FluxML/MLJFlux.jl" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>encoding</category>
      <category>gsoc</category>
      <category>jsoc</category>
    </item>
    <item>
      <title>Why you might avoid `deepcopy` in Julia</title>
      <dc:creator>Eric Hanson</dc:creator>
      <pubDate>Sun, 21 Jul 2024 11:45:20 +0000</pubDate>
      <link>https://forem.julialang.org/ericphanson/why-you-might-avoid-deepcopy-in-julia-10cp</link>
      <guid>https://forem.julialang.org/ericphanson/why-you-might-avoid-deepcopy-in-julia-10cp</guid>
      <description>&lt;h2&gt;
  
  
  Why use &lt;code&gt;deepcopy&lt;/code&gt;?
&lt;/h2&gt;

&lt;p&gt;In &lt;a href="https://julialang.org/" rel="noopener noreferrer"&gt;Julia&lt;/a&gt;, &lt;a href="https://docs.julialang.org/en/v1/base/base/#Base.copy" rel="noopener noreferrer"&gt;&lt;code&gt;copy&lt;/code&gt;&lt;/a&gt; is a function which creates a shallow copy. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight julia"&gt;&lt;code&gt;&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt; &lt;span class="c"&gt;# vector with one element, namely 1&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt; &lt;span class="kt"&gt;Vector&lt;/span&gt;&lt;span class="x"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;Int64&lt;/span&gt;&lt;span class="x"&gt;}&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
 &lt;span class="mi"&gt;1&lt;/span&gt;

&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt; &lt;span class="c"&gt;# vector with one element, `a`&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt; &lt;span class="kt"&gt;Vector&lt;/span&gt;&lt;span class="x"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;Vector&lt;/span&gt;&lt;span class="x"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;Int64&lt;/span&gt;&lt;span class="x"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
 &lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;b2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;copy&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt; &lt;span class="c"&gt;# new vector, also with one element which is `a`&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt; &lt;span class="kt"&gt;Vector&lt;/span&gt;&lt;span class="x"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;Vector&lt;/span&gt;&lt;span class="x"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;Int64&lt;/span&gt;&lt;span class="x"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
 &lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;push!&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt; &lt;span class="c"&gt;# mutate `a` so it contains 1 and 2&lt;/span&gt;
&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt; &lt;span class="kt"&gt;Vector&lt;/span&gt;&lt;span class="x"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;Int64&lt;/span&gt;&lt;span class="x"&gt;}&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
 &lt;span class="mi"&gt;1&lt;/span&gt;
 &lt;span class="mi"&gt;2&lt;/span&gt;

&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="c"&gt;# since `b` contains `a`, we can see its (nested) contents have changed&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt; &lt;span class="kt"&gt;Vector&lt;/span&gt;&lt;span class="x"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;Vector&lt;/span&gt;&lt;span class="x"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;Int64&lt;/span&gt;&lt;span class="x"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
 &lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;b2&lt;/span&gt; &lt;span class="c"&gt;# same for `b2`!&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt; &lt;span class="kt"&gt;Vector&lt;/span&gt;&lt;span class="x"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;Vector&lt;/span&gt;&lt;span class="x"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;Int64&lt;/span&gt;&lt;span class="x"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
 &lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since &lt;code&gt;copy&lt;/code&gt; is shallow, &lt;code&gt;b2&lt;/code&gt; still contains the same vector &lt;code&gt;a&lt;/code&gt; (whose contents we modified to be &lt;code&gt;[1,2]&lt;/code&gt;), just like &lt;code&gt;b&lt;/code&gt;, even though they are independent vectors which do not share memory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight julia"&gt;&lt;code&gt;&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;push!&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="x"&gt;])&lt;/span&gt; &lt;span class="c"&gt;# mutate `b`&lt;/span&gt;
&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt; &lt;span class="kt"&gt;Vector&lt;/span&gt;&lt;span class="x"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;Vector&lt;/span&gt;&lt;span class="x"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;Int64&lt;/span&gt;&lt;span class="x"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
 &lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt;
 &lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;b2&lt;/span&gt; &lt;span class="c"&gt;# not mutated&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt; &lt;span class="kt"&gt;Vector&lt;/span&gt;&lt;span class="x"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;Vector&lt;/span&gt;&lt;span class="x"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;Int64&lt;/span&gt;&lt;span class="x"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
 &lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In contrast, &lt;a href="https://docs.julialang.org/en/v1/base/base/#Base.deepcopy" rel="noopener noreferrer"&gt;&lt;code&gt;deepcopy&lt;/code&gt;&lt;/a&gt; is a function which recursively copies objects:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight julia"&gt;&lt;code&gt;&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt; &lt;span class="c"&gt;# vector with one element, namely 1&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt; &lt;span class="kt"&gt;Vector&lt;/span&gt;&lt;span class="x"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;Int64&lt;/span&gt;&lt;span class="x"&gt;}&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
 &lt;span class="mi"&gt;1&lt;/span&gt;

&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt; &lt;span class="c"&gt;# vector with one element, `a`&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt; &lt;span class="kt"&gt;Vector&lt;/span&gt;&lt;span class="x"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;Vector&lt;/span&gt;&lt;span class="x"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;Int64&lt;/span&gt;&lt;span class="x"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
 &lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;b2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;deepcopy&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt; &lt;span class="c"&gt;# new vector, with new contents&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt; &lt;span class="kt"&gt;Vector&lt;/span&gt;&lt;span class="x"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;Vector&lt;/span&gt;&lt;span class="x"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;Int64&lt;/span&gt;&lt;span class="x"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
 &lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;push!&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt; &lt;span class="c"&gt;# mutate `a` so it contains 1 and 2&lt;/span&gt;
&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt; &lt;span class="kt"&gt;Vector&lt;/span&gt;&lt;span class="x"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;Int64&lt;/span&gt;&lt;span class="x"&gt;}&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
 &lt;span class="mi"&gt;1&lt;/span&gt;
 &lt;span class="mi"&gt;2&lt;/span&gt;

&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt; &lt;span class="kt"&gt;Vector&lt;/span&gt;&lt;span class="x"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;Vector&lt;/span&gt;&lt;span class="x"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;Int64&lt;/span&gt;&lt;span class="x"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
 &lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;b2&lt;/span&gt; &lt;span class="c"&gt;# contents are unchanged&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt; &lt;span class="kt"&gt;Vector&lt;/span&gt;&lt;span class="x"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;Vector&lt;/span&gt;&lt;span class="x"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;Int64&lt;/span&gt;&lt;span class="x"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
 &lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can see that &lt;code&gt;b2&lt;/code&gt; still just contains &lt;code&gt;[1]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It's easy to see why &lt;code&gt;deepcopy&lt;/code&gt; might be appealing: it could be surprising that modifying &lt;code&gt;a&lt;/code&gt; affects &lt;code&gt;b2&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Note also that &lt;code&gt;deepcopy&lt;/code&gt; also has some other nice properties. For example, note here that since &lt;code&gt;b&lt;/code&gt; contains &lt;code&gt;a&lt;/code&gt; twice, modifying &lt;code&gt;a&lt;/code&gt; has the following effect on &lt;code&gt;b&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight julia"&gt;&lt;code&gt;&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt; &lt;span class="kt"&gt;Vector&lt;/span&gt;&lt;span class="x"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;Int64&lt;/span&gt;&lt;span class="x"&gt;}&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
 &lt;span class="mi"&gt;1&lt;/span&gt;

&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt;
&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt; &lt;span class="kt"&gt;Vector&lt;/span&gt;&lt;span class="x"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;Vector&lt;/span&gt;&lt;span class="x"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;Int64&lt;/span&gt;&lt;span class="x"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
 &lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt;
 &lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;push!&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt; &lt;span class="kt"&gt;Vector&lt;/span&gt;&lt;span class="x"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;Int64&lt;/span&gt;&lt;span class="x"&gt;}&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
 &lt;span class="mi"&gt;1&lt;/span&gt;
 &lt;span class="mi"&gt;2&lt;/span&gt;

&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt; &lt;span class="kt"&gt;Vector&lt;/span&gt;&lt;span class="x"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;Vector&lt;/span&gt;&lt;span class="x"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;Int64&lt;/span&gt;&lt;span class="x"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
 &lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt;
 &lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;deepcopy&lt;/code&gt; preserves this internal structure. Continuing the example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight julia"&gt;&lt;code&gt;&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;b2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;deepcopy&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt; &lt;span class="kt"&gt;Vector&lt;/span&gt;&lt;span class="x"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;Vector&lt;/span&gt;&lt;span class="x"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;Int64&lt;/span&gt;&lt;span class="x"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
 &lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt;
 &lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;b2&lt;/span&gt;&lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt;
&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt; &lt;span class="kt"&gt;Vector&lt;/span&gt;&lt;span class="x"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;Int64&lt;/span&gt;&lt;span class="x"&gt;}&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
 &lt;span class="mi"&gt;1&lt;/span&gt;
 &lt;span class="mi"&gt;2&lt;/span&gt;

&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;push!&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a2&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt; &lt;span class="kt"&gt;Vector&lt;/span&gt;&lt;span class="x"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;Int64&lt;/span&gt;&lt;span class="x"&gt;}&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
 &lt;span class="mi"&gt;1&lt;/span&gt;
 &lt;span class="mi"&gt;2&lt;/span&gt;
 &lt;span class="mi"&gt;3&lt;/span&gt;

&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;b2&lt;/span&gt;
&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt; &lt;span class="kt"&gt;Vector&lt;/span&gt;&lt;span class="x"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;Vector&lt;/span&gt;&lt;span class="x"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;Int64&lt;/span&gt;&lt;span class="x"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
 &lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt;
 &lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pretty nice! Semantically, &lt;code&gt;deepcopy&lt;/code&gt; should be the same as composing &lt;a href="https://docs.julialang.org/en/v1/stdlib/Serialization/#Serialization.deserialize" rel="noopener noreferrer"&gt;&lt;code&gt;deserialize&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://docs.julialang.org/en/v1/stdlib/Serialization/#Serialization.serialize" rel="noopener noreferrer"&gt;&lt;code&gt;serialize&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why not use &lt;code&gt;deepcopy&lt;/code&gt;?
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;deepcopy&lt;/code&gt; is reaching into the internals of the object, rather than relying on the API of the object (namely, its method for &lt;code&gt;copy&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;It's easy to construct cases in which this is semantically incorrect. For example, lets say we are constructing our own vector type which stores its memory elsewhere, and stores a token to use to lookup the memory. Here is a quick implementation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight julia"&gt;&lt;code&gt;&lt;span class="c"&gt;# mutable so each instance has its own identity&lt;/span&gt;
&lt;span class="k"&gt;mutable struct&lt;/span&gt;&lt;span class="nc"&gt; Token&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;STORAGE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Dict&lt;/span&gt;&lt;span class="x"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Token&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Vector&lt;/span&gt;&lt;span class="x"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;Float64&lt;/span&gt;&lt;span class="x"&gt;}}()&lt;/span&gt;

&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="nc"&gt; MyVectorType&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;:&lt;/span&gt; &lt;span class="kt"&gt;AbstractVector&lt;/span&gt;&lt;span class="x"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;Float64&lt;/span&gt;&lt;span class="x"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Token&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="c"&gt;# construction from a `vector`&lt;/span&gt;
&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="nf"&gt; MyVectorType&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="kt"&gt;Vector&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Token&lt;/span&gt;&lt;span class="x"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;STORAGE&lt;/span&gt;&lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;MyVectorType&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="n"&gt;Base&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getindex&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;MyVectorType&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;STORAGE&lt;/span&gt;&lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="x"&gt;][&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;Base&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setindex!&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;MyVectorType&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;STORAGE&lt;/span&gt;&lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="x"&gt;][&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;
&lt;span class="n"&gt;Base&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;MyVectorType&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;STORAGE&lt;/span&gt;&lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="x"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="nf"&gt; Base.copy&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;MyVectorType&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;MyVectorType&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;copy&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;STORAGE&lt;/span&gt;&lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="x"&gt;]))&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight julia"&gt;&lt;code&gt;&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MyVectorType&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rand&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="x"&gt;))&lt;/span&gt;
&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt; &lt;span class="n"&gt;MyVectorType&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
 &lt;span class="mf"&gt;0.49321258978106763&lt;/span&gt;
 &lt;span class="mf"&gt;0.6022070713363459&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then &lt;code&gt;copy&lt;/code&gt; works as expected, since we defined a method for it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight julia"&gt;&lt;code&gt;&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;v2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;copy&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt; &lt;span class="n"&gt;MyVectorType&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
 &lt;span class="mf"&gt;0.49321258978106763&lt;/span&gt;
 &lt;span class="mf"&gt;0.6022070713363459&lt;/span&gt;

&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;2.0&lt;/span&gt;
&lt;span class="mf"&gt;2.0&lt;/span&gt;

&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;
&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt; &lt;span class="n"&gt;MyVectorType&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
 &lt;span class="mf"&gt;2.0&lt;/span&gt;
 &lt;span class="mf"&gt;0.6022070713363459&lt;/span&gt;

&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;v2&lt;/span&gt;
&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt; &lt;span class="n"&gt;MyVectorType&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
 &lt;span class="mf"&gt;0.49321258978106763&lt;/span&gt;
 &lt;span class="mf"&gt;0.6022070713363459&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But &lt;code&gt;deepcopy&lt;/code&gt; fails:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight julia"&gt;&lt;code&gt;&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;deepcopy&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;Error&lt;/span&gt; &lt;span class="n"&gt;showing&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt; &lt;span class="n"&gt;MyVectorType&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="n"&gt;ERROR&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;KeyError&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="n"&gt;Token&lt;/span&gt;&lt;span class="x"&gt;()&lt;/span&gt; &lt;span class="n"&gt;not&lt;/span&gt; &lt;span class="n"&gt;found&lt;/span&gt;
&lt;span class="n"&gt;Stacktrace&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
  &lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt; &lt;span class="n"&gt;getindex&lt;/span&gt;
    &lt;span class="err"&gt;@&lt;/span&gt; &lt;span class="o"&gt;./&lt;/span&gt;&lt;span class="n"&gt;dict&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;jl&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;477&lt;/span&gt; &lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="n"&gt;inlined&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt;
  &lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;
    &lt;span class="err"&gt;@&lt;/span&gt; &lt;span class="o"&gt;./&lt;/span&gt;&lt;span class="n"&gt;REPL&lt;/span&gt;&lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="n"&gt;inlined&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It has constructed new &lt;code&gt;Token&lt;/code&gt; instance which does not have a corresponding entry in &lt;code&gt;STORAGE&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Using &lt;code&gt;deepcopy&lt;/code&gt;, we have made assumptions about the implementation details of how &lt;code&gt;MyVectorType&lt;/code&gt; works and constructed an invalid instance!&lt;/p&gt;

&lt;p&gt;One can run into similar problems when the object contains references to memory allocated in another language, see e.g. &lt;a href="https://github.com/jump-dev/JuMP.jl/pull/2079" rel="noopener noreferrer"&gt;JuMP's rationale for disabling &lt;code&gt;deepcopy&lt;/code&gt; on its models&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Revisiting reasons to use &lt;code&gt;deepcopy&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Sometimes, feeling a need to use &lt;code&gt;deepcopy&lt;/code&gt; is actually a hint that something else is wrong. I think the main one is missing &lt;code&gt;copy&lt;/code&gt; methods, but I believe there might be several other reasons; if you think of one, let me know and I might add it here.&lt;/p&gt;

&lt;h3&gt;
  
  
  "Missing" &lt;code&gt;copy&lt;/code&gt; method
&lt;/h3&gt;

&lt;p&gt;I think one of the most common reasons to reach for &lt;code&gt;deepcopy&lt;/code&gt; is that one of the objects you are working with is missing a &lt;code&gt;copy&lt;/code&gt; method, or it is not copying quite what it should&lt;sup id="fnref1"&gt;1&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;While &lt;code&gt;copy&lt;/code&gt; is defined to be a "shallow" copy, it is not always totally clear exactly how deep or shallow that should be. Adding semantics around whether the object represents a nested or flat datastructure can clarify this.&lt;/p&gt;

&lt;p&gt;For example, a &lt;code&gt;DataFrame&lt;/code&gt; is semantically a 2D object, which is implemented with a vector-of-vectors similar to our &lt;code&gt;b&lt;/code&gt; in the first example. &lt;code&gt;DataFrame&lt;/code&gt; defines a &lt;code&gt;copy&lt;/code&gt; method which by default &lt;em&gt;does&lt;/em&gt; copy the nested inner vectors, but &lt;em&gt;not&lt;/em&gt; any of their contents. I believe this is semantically correct, because the vector-of-vectors construction is simply an implementation detail of &lt;code&gt;DataFrame&lt;/code&gt;, and the object itself is a flat 2D object (as shown by e.g. &lt;code&gt;size&lt;/code&gt;), and therefore &lt;code&gt;copy&lt;/code&gt; should not behave like it is a vector-of-vectors.&lt;/p&gt;

&lt;p&gt;Sometimes &lt;code&gt;deepcopy&lt;/code&gt; usage hints at both a "missing" struct definition and copy method. For example, when using nested dictionaries to store configuration state, one might start with a "default configuration", then &lt;code&gt;deepcopy&lt;/code&gt; it to pass to a user to modify. This seems practical and totally fine, but it might be nicer to wrap up the configuration in a &lt;code&gt;struct&lt;/code&gt; and define a &lt;code&gt;copy&lt;/code&gt; method for it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Should you use &lt;code&gt;deepcopy&lt;/code&gt;?
&lt;/h2&gt;

&lt;p&gt;Maybe! It depends on the situation. To me it is often a sign that some abstraction is not working as intended, or a &lt;code&gt;copy&lt;/code&gt; method is missing somewhere. But it is a good workaround, and sometimes a useful shortcut in some scenarios like writing tests, and there are situations in which it seems like the correct tool for the job.&lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;Note: in this case, using &lt;code&gt;deepcopy&lt;/code&gt; may be the best way to stay unblocked in this situation! I don't think there's anything wrong with using it as a workaround, but it may signal there is an upstream issue somewhere to be filed or fixed. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
    </item>
    <item>
      <title>AIHelpMe.jl Pt.2: Instant Expertise, Infinite Solutions for Julia Developers</title>
      <dc:creator>Jan Siml</dc:creator>
      <pubDate>Tue, 30 Apr 2024 08:36:09 +0000</pubDate>
      <link>https://forem.julialang.org/svilupp/aihelpmejl-pt2-instant-expertise-infinite-solutions-for-julia-developers-a31</link>
      <guid>https://forem.julialang.org/svilupp/aihelpmejl-pt2-instant-expertise-infinite-solutions-for-julia-developers-a31</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/svilupp/AIHelpMe.jl"&gt;AIHelpMe.jl&lt;/a&gt; is a Julia package that harnesses the power of AI models to provide tailored coding guidance, integrating seamlessly with PromptingTools.jl to offer a unique approach to answering coding queries directly in Julia's environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Frustration of Searching for Julia Answers
&lt;/h2&gt;

&lt;p&gt;We've all been there. You're stuck on a problem, and you need some guidance on how to implement a specific functionality in Julia. You head to your trusty search engine, type in your query, and... wait, why are all these results in Python? You tweak your query, adding "Julia" this and "Julia language" that, but still, the results are scattered and unclear.&lt;/p&gt;

&lt;p&gt;After 5 minutes of searching, you finally stumble upon a Discourse post from 2018. But wait, is this even relevant to Julia 1.0? Should you bother opening it? You take a deep breath and dive in, hoping that the answer lies within.&lt;/p&gt;

&lt;p&gt;Another 5 minutes pass, and you finally find what you're looking for. You copy out the necessary snippet, and after a few more minutes of customizing it to your needs, you have what you needed. The process is tedious, to say the least.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction to AIHelpMe's Official Release
&lt;/h2&gt;

&lt;p&gt;AIHelpMe, a Julia package designed to enhance coding assistance with AI, has been officially registered and released. This milestone makes it easier to install directly from the Julia registry and introduces new functionalities and new knowledge packs! Now, developers can access sophisticated, AI-powered coding guidance more efficiently than ever.&lt;/p&gt;

&lt;h2&gt;
  
  
  How AIHelpMe Works
&lt;/h2&gt;

&lt;p&gt;AIHelpMe uses a Retrieval Augment Generation (RAG) pattern to provide accurate and relevant answers to your coding questions. It preprocesses the provided documentation, converting text snippets into numerical embeddings. When you ask a question, AIHelpMe looks up the most relevant documentation snippets, feeds them into the AI model, and generates an answer tailored to Julia's ecosystem and best practices.&lt;/p&gt;

&lt;p&gt;Get started with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight julia"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="n"&gt;Pkg&lt;/span&gt;
&lt;span class="n"&gt;Pkg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"AIHelpMe"&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="n"&gt;AIHelpMe&lt;/span&gt;
&lt;span class="n"&gt;aihelp&lt;/span&gt;&lt;span class="s"&gt;"How do I implement quicksort in Julia?"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note: It requires at least the OpenAI API key (&lt;code&gt;ENV["OPENAI_API_KEY"]&lt;/code&gt;), but I would strongly recommend getting a FREE Cohere API key for re-ranking (silver pipeline).&lt;/p&gt;

&lt;h2&gt;
  
  
  How AIHelpMe Differs from Other Solutions
&lt;/h2&gt;

&lt;p&gt;Compared to chatbots, AIHelpMe offers several advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Grounded in actual resources&lt;/strong&gt;: AIHelpMe's answers are based on actual, up-to-date Julia resources, not outdated training data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customizable knowledge&lt;/strong&gt;: You choose what knowledge to include, allowing you to improve precision and recall.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flexible trade-offs&lt;/strong&gt;: You choose the trade-off between cost, performance, and time, giving you greater control over your coding experience.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;State-of-the-art RAG methods&lt;/strong&gt;: AIHelpMe leverages the latest RAG methods, and full customization is possible, ensuring that you get the most accurate and relevant answers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note: Only a limited number of packages have been pre-processed so far: Julia docs, Tidier ecosystem, and Makie ecosystem. It's still experimental, but it works! Load them with:&lt;/p&gt;

&lt;h2&gt;
  
  
  Starter Example
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight julia"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="n"&gt;AIHelpMe&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="n"&gt;AIHelpMe&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pprint&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;last_result&lt;/span&gt;

&lt;span class="c"&gt;# ideally, switch to better pipeline for proper results, requires setting up Cohere API key&lt;/span&gt;
&lt;span class="n"&gt;AIHelpMe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;update_pipeline!&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;silver&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# load tidier index, others available: :julia, :makie&lt;/span&gt;
&lt;span class="n"&gt;AIHelpMe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load_index!&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;tidier&lt;/span&gt;&lt;span class="x"&gt;);&lt;/span&gt;

&lt;span class="c"&gt;# Ask a question&lt;/span&gt;
&lt;span class="n"&gt;aihelp&lt;/span&gt;&lt;span class="s"&gt;"How do you add a regression line to a plot in TidierPlots?"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://forem.julialang.org/images/faBQBVouq4IGJYEyWmwiflkqwFTIPEm33jqWzLBMDrw/rt:fit/w:800/g:sm/q:0/mb:500000/ar:1/aHR0cHM6Ly9mb3Jl/bS5qdWxpYWxhbmcu/b3JnL3JlbW90ZWlt/YWdlcy91cGxvYWRz/L2FydGljbGVzL2ky/bWhoNzEzOGd3MDll/c2Q3ajZsLnBuZw" class="article-body-image-wrapper"&gt;&lt;img src="https://forem.julialang.org/images/faBQBVouq4IGJYEyWmwiflkqwFTIPEm33jqWzLBMDrw/rt:fit/w:800/g:sm/q:0/mb:500000/ar:1/aHR0cHM6Ly9mb3Jl/bS5qdWxpYWxhbmcu/b3JnL3JlbW90ZWlt/YWdlcy91cGxvYWRz/L2FydGljbGVzL2ky/bWhoNzEzOGd3MDll/c2Q3ajZsLnBuZw" alt="Quick answer over Tidier docs" width="800" height="99"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Or show the highlighted answer (you can customize to add the actual source docs, or remove the scores/highlights):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight julia"&gt;&lt;code&gt;&lt;span class="c"&gt;# See highlighted answer (optional)&lt;/span&gt;
&lt;span class="n"&gt;pprint&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;last_result&lt;/span&gt;&lt;span class="x"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://forem.julialang.org/images/xsOj3_BGTAxyLVFcS2sBSaDC2UCwmcfMbMdGhnsfb-w/rt:fit/w:800/g:sm/q:0/mb:500000/ar:1/aHR0cHM6Ly9mb3Jl/bS5qdWxpYWxhbmcu/b3JnL3JlbW90ZWlt/YWdlcy91cGxvYWRz/L2FydGljbGVzL3g2/ZWE2bmEwbnFjZzl1/bDd0dnNqLnBuZw" class="article-body-image-wrapper"&gt;&lt;img src="https://forem.julialang.org/images/xsOj3_BGTAxyLVFcS2sBSaDC2UCwmcfMbMdGhnsfb-w/rt:fit/w:800/g:sm/q:0/mb:500000/ar:1/aHR0cHM6Ly9mb3Jl/bS5qdWxpYWxhbmcu/b3JnL3JlbW90ZWlt/YWdlcy91cGxvYWRz/L2FydGljbGVzL3g2/ZWE2bmEwbnFjZzl1/bDd0dnNqLnBuZw" alt="Highlighted answer over Tidier docs" width="800" height="180"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you're an infrequent user of AlgebraOfGraphics like me, you'll certainly appreciate the &lt;code&gt;:makie&lt;/code&gt; knowledge pack -- it's much faster now to find the right keywords to customize your plot!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight julia"&gt;&lt;code&gt;&lt;span class="c"&gt;# Load all knowledge packs&lt;/span&gt;
&lt;span class="n"&gt;AIHelpMe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load_index!&lt;/span&gt;&lt;span class="x"&gt;([&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;makie&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;tidier&lt;/span&gt;&lt;span class="x"&gt;]);&lt;/span&gt;
&lt;span class="n"&gt;aihelp&lt;/span&gt;&lt;span class="s"&gt;"How to set the label of a y-axis in Makie?"&lt;/span&gt;&lt;span class="n"&gt;gpt3t&lt;/span&gt; &lt;span class="c"&gt;# testing a weak model&lt;/span&gt;
&lt;span class="n"&gt;pprint&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;last_result&lt;/span&gt;&lt;span class="x"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://forem.julialang.org/images/K8DTFgnTOBE0Tq578jo9PR-zn6wdMtUxp5lhm0-XFxg/rt:fit/w:800/g:sm/q:0/mb:500000/ar:1/aHR0cHM6Ly9mb3Jl/bS5qdWxpYWxhbmcu/b3JnL3JlbW90ZWlt/YWdlcy91cGxvYWRz/L2FydGljbGVzLzNw/eTd0Ym02emFnbjI5/dnRsaml1LnBuZw" class="article-body-image-wrapper"&gt;&lt;img src="https://forem.julialang.org/images/K8DTFgnTOBE0Tq578jo9PR-zn6wdMtUxp5lhm0-XFxg/rt:fit/w:800/g:sm/q:0/mb:500000/ar:1/aHR0cHM6Ly9mb3Jl/bS5qdWxpYWxhbmcu/b3JnL3JlbW90ZWlt/YWdlcy91cGxvYWRz/L2FydGljbGVzLzNw/eTd0Ym02emFnbjI5/dnRsaml1LnBuZw" alt="Highlighted answer over Makie docs" width="800" height="240"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note: There can still be some issues with the quality of the answers (it's GenAI!), especially for the bronze pipeline and weaker models, but, hopefully, it's already good enough to create value for you!&lt;/p&gt;

&lt;h2&gt;
  
  
  Advanced Usage of AIHelpMe
&lt;/h2&gt;

&lt;p&gt;AIHelpMe offers several advanced features for experienced users wanting more control and deeper insights:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Response Insights:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;code&gt;pprint&lt;/code&gt; to highlight potential hallucinations, show sources, their scores, and context snippets.&lt;/li&gt;
&lt;li&gt;Example: &lt;code&gt;aihelp("Explain Julia's multiple dispatch system", return_all=true)|&amp;gt;AIHelpMe.pprint&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note: You'll always get better responses with better pipelines - see below.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Customizing the AI Pipeline:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adjust the complexity of AI responses with &lt;code&gt;update_pipeline!&lt;/code&gt; choosing from bronze, silver, or gold levels.&lt;/li&gt;
&lt;li&gt;Specify AI models, including local options like Ollama.&lt;/li&gt;
&lt;li&gt;Example: &lt;code&gt;AIHelpMe.update_pipeline!(:silver; model="gllama370")&lt;/code&gt; # gllama370 is Groq.com-hosted Llama 3 70b that you can access for free!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Safe Code Execution:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Execute AI-generated code safely with &lt;code&gt;PromptingTools.AICode&lt;/code&gt; struct.&lt;/li&gt;
&lt;li&gt;Example: &lt;code&gt;aihelp("How to create a named tuple from a dictionary?")|&amp;gt;PromptingTools.AICode&lt;/code&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For more details on these advanced features, please refer to the &lt;a href="https://svilupp.github.io/svilupp.github.io/AIHelpMe.jl/dev/advanced"&gt;AIHelpMe Advanced Documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;Over the summer, we hope to optimize the performance (in terms of quality) and add more knowledge packs. &lt;/p&gt;

&lt;p&gt;We're also working on making it super easy for you to develop your own knowledge packs for the packages you use, regardless of whether they're public or private. This will enable you to tailor AIHelpMe to your specific needs and workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;AIHelpMe is the solution to your Julia coding woes. With its AI-powered assistance, flexible querying system, and cost-effective approach, AIHelpMe is poised to revolutionize the way you code in Julia. Try it out today and experience the future of coding assistance!&lt;/p&gt;

&lt;p&gt;Credit for the title image: DALL-E 3.&lt;/p&gt;

</description>
      <category>genai</category>
      <category>generativeai</category>
      <category>aihelpme</category>
    </item>
    <item>
      <title>ProToPortal: The Portal to the Magic of PromptingTools</title>
      <dc:creator>Jan Siml</dc:creator>
      <pubDate>Sun, 28 Apr 2024 16:02:47 +0000</pubDate>
      <link>https://forem.julialang.org/svilupp/protoportal-the-portal-to-the-magic-of-promptingtools-47n2</link>
      <guid>https://forem.julialang.org/svilupp/protoportal-the-portal-to-the-magic-of-promptingtools-47n2</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;ProToPortal streamlines your interaction with any LLM tasks on the go, offering customizable templates for automatic replies, direct code evaluation, and an intuitive, multi-device interface. Explore its full capabilities and enhance your productivity on &lt;a href="https://github.com/svilupp/ProToPortal.jl"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Unveiling ProToPortal: A Julia-First LLM GUI built with Stipple.jl!
&lt;/h2&gt;

&lt;p&gt;Hello, fellow GenAI enthusiasts! Today, I'm thrilled to introduce &lt;strong&gt;ProToPortal&lt;/strong&gt;, a nifty tool born from my own need to simplify my daily interactions with Julia and AI models. It's a small but mighty project aimed at boosting productivity and minimizing those pesky prompting hassles.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why ProToPortal?
&lt;/h2&gt;

&lt;p&gt;Ever found yourself on a leisurely walk with your dog, struck by a sudden coding inspiration that just couldn't wait? That's exactly where ProToPortal comes into play. This tool isn't just another coding interface; it's your on-the-go, in-your-pocket coding companion, ready to tackle tasks from simple prompts to complex code evaluations—all before you've even finished your walk!&lt;/p&gt;

&lt;h2&gt;
  
  
  Cool Features to Check Out:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Accessible Anywhere:&lt;/strong&gt; Whether you're on a train or in your comfy home office, ProToPortal is there. It works seamlessly across all devices, ensuring that your brilliant ideas never slip away just because you're not at your desk.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Code Evaluation and Fixing:&lt;/strong&gt; Forget about flipping between screens to debug. ProToPortal lets you directly evaluate and fix Julia code within the GUI. Imagine tweaking your code with just a few clicks—yes, it's that easy!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Automatic Replies:&lt;/strong&gt; Streamline your workflow even further with automated responses. Set up ProToPortal to handle repetitive tasks, leaving you more time to focus on the creative aspects of coding.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  More Handy Features:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Editing Code Cells:&lt;/strong&gt; Quickly edit any of the messages right within the chat tab—just click and modify.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deleting Code Cells:&lt;/strong&gt; Made a mistake? No worries! Easily remove any unwanted messages.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Saving Conversations:&lt;/strong&gt; Keep a history of your sessions for future reference or continued experimentation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a complete list of features, including detailed explanations and how-tos, be sure to check out &lt;a href="https://svilupp.github.io/ProToPortal.jl/dev"&gt;ProToPortal's Documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  See It in Action:
&lt;/h2&gt;

&lt;p&gt;Curious to see how it works in real time? &lt;/p&gt;

&lt;p&gt;Check out this video where it auto-fixes the generated code: &lt;a href="https://github.com/svilupp/ProToPortal.jl/blob/main/docs/src/videos/screen-capture-code-fixing.webm"&gt;Code fixing recording&lt;/a&gt; (webm format so not all browsers might play it).&lt;/p&gt;

&lt;p&gt;And here's another cool feature—watch how ProToPortal handles editing a conversation (gif, easy to play): &lt;a href="https://github.com/svilupp/ProToPortal.jl/blob/9eb18346d056dd1b3b4d2202ce5da0b7be7ef8cb/docs/src/videos/screen-capture-plain.gif"&gt;Editing a conversation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Give It a Try!
&lt;/h2&gt;

&lt;p&gt;Ready to dive in? Visit &lt;a href="https://github.com/svilupp/ProToPortal.jl"&gt;ProToPortal's GitHub&lt;/a&gt; to get started. It's open source, and I'm eager to hear your thoughts or see your contributions!&lt;/p&gt;

&lt;p&gt;Thanks for checking out ProToPortal. Happy coding, and let the code be with you!&lt;/p&gt;




&lt;p&gt;Big thank you to the &lt;a href="https://genieframework.com/"&gt;Genie.jl&lt;/a&gt; team! This tool wouldn't exist without their amazing packages!&lt;/p&gt;

&lt;p&gt;Credit for the title image goes to DALL-E 3.&lt;/p&gt;

</description>
      <category>generativeai</category>
      <category>genai</category>
      <category>genie</category>
    </item>
  </channel>
</rss>
