Skip to content

Instantly share code, notes, and snippets.

@tkf
Last active July 7, 2019 03:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tkf/85a0751820f2be4a6aaa707959e7cd96 to your computer and use it in GitHub Desktop.
Save tkf/85a0751820f2be4a6aaa707959e7cd96 to your computer and use it in GitHub Desktop.
#!/bin/bash
# -*- mode: julia -*-
#=
JULIA="${JULIA:-julia --color=yes --startup-file=no}"
exec ${JULIA} "${BASH_SOURCE[0]}" "$@"
=#
using Literate
Literate.markdown(joinpath(@__DIR__, "scanscan.jl"), joinpath(@__DIR__, "src"))
import DocumenterMarkdown
using Documenter
makedocs(format=DocumenterMarkdown.Markdown())
.PHONY: md ipynb all
md: build/scanscan.md
ipynb: build/scanscan.ipynb
all: md ipynb
build/scanscan.md: scanscan.jl
./make.jl
build/scanscan.ipynb: scanscan.jl
mkdir -pv build
julia --color=yes --startup-file=no -e \
'using Literate; Literate.notebook("scanscan.jl", "build")'
# # Nested `Scan` cannot be inferred (and inference results are confusing)
#
# This post is generated from this script:
# https://gist.github.com/85a0751820f2be4a6aaa707959e7cd96
#
# ## Examples
using Test
using Transducers
function showingerror(f)
err = nothing
try
f()
catch err
showerror(stdout, err)
end
@assert err !== nothing
end
nothing # hide
# Currently, nested `Scan` cannot be inferred (in most of the cases):
showingerror() do
@inferred foldl(*, Scan(+) |> Scan(+), 1:1)
end
# Specifying initial value (`init=1`) does not help:
showingerror() do
@inferred foldl(*, Scan(+) |> Scan(+), 1:1; init=1)
end
# Side note: In some REPL sessions, following actually could be
# inferred. But now I can't reproduce this...
#
# ```julia
# foldl(*, Scan(+) |> Map(x -> x::Int) |> Scan(+), 1:1)
# foldl(right, Scan(+) |> Scan(+) |> Scan(+) |> Scan(+), 1:1)
# ```
# ## Looking into the Julia IR
#
# Using `@descend foldl(*, Scan(+) |> Scan(+), 1:1)`, it looks like
# the inference of the first example failed in
using InteractiveUtils
using Transducers: _start_init, __foldl__
rf = reducingfunction(Scan(+) |> Scan(+), *)
state = _start_init(rf, 1)
if VERSION < v"1.2-"
@code_warntype __foldl__(rf, state, 1:1)
else
@code_warntype optimize=true __foldl__(rf, state, 1:1)
end
# The first type instability occurs at
#
# %62 = invoke Transducers.wrapping(...)
#
# which is inferred to return
#
# ```julia
# Union{
# PrivateState{
# Reduction{
# Scan{typeof(+),Initials.InitialOf{typeof(+)}},
# Reduction{Scan{typeof(+),Initials.InitialOf{typeof(+)}},BottomRF{NOTYPE,typeof(*)},NOTYPE},
# NOTYPE,
# },
# Int64,
# _A,
# } where _A,
# Reduced,
# }
# ```
#
# where the type variable `_A` Julia couldn't infer (or chose to
# ignore?) is the inner result type (which is again a `PrivateState`
# here).
# Confusingly, inferring `Transducers.wrapping` by (1) using
# `@descend` or by (2) running `@code_warntype` on `next` which in
# turn calls `wrapping` as below says it actually is inferrable:
using Transducers: next
@code_warntype next(rf, state, 1)
# More confusingly, `@inferred` reports the result as in `%62` above
# (similar report: https://discourse.julialang.org/t/24998)
showingerror() do
@inferred next(rf, state, 1)
end
# Maybe there is some threshold in the inference which stops trying to
# run on nested calls when the argument is too complex or something?
# ### Version information
# Julia
VERSION
# Transducers
print(read(`recrepo --pretty --output=- $(pathof(Transducers))`, String))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment