Merefleksikan Makro |  juliablogger.com

 – Beragampengetahuan
1 min read

Merefleksikan Makro | juliablogger.com – Beragampengetahuan

Pengarang: Jonathan Caroll

Repost dari:

Saya menonton film tentang RustConf Keynote Fiasco (RKNF, per @fasterthanlime)
dari jarak yang sangat jauh – saya tidak berpartisipasi dalam komunitas itu selain untuk mulai belajar
bahasa. Tapi topik kontroversial Refleksi Waktu Kompilasi itu sendiri sepertinya hal yang menarik yang bisa saya pelajari.

Awal yang baik biasanya halaman Wikipedia, dan saya menemukan satu yang disebut “Pemrograman Reflektif” di bagian “Pemrograman Meta”
genre, di mana ia mendefinisikan

Refleksi adalah kemampuan suatu proses untuk memeriksa, introspeksi, dan memodifikasi struktur dan perilakunya sendiri

Kedengarannya agak familiar dari apa yang saya baca tentang metaprogramming. Salah satu dari
Fitur hebat dari R adalah kemampuan untuk menguji dan menulis ulang fungsi, misalnya:
tubuh dari sd() fungsi (menghitung standar deviasi input) terlihat
sama

sd
## function (x, na.rm = FALSE) 
## sqrt(var(if (is.vector(x) || is.factor(x)) x else as.double(x), 
##     na.rm = na.rm))
## <bytecode: 0x55a797b52960>
## <environment: namespace:stats>

Mencoba mengekstrak “komponen” dari fungsi tersebut menghasilkan kesalahan kanonis

sd[1]
## Error in sd[1]: object of type 'closure' is not subsettable

Namunmenggunakan body() Kami Mungkin pada komponen fungsi

body(sd)
## sqrt(var(if (is.vector(x) || is.factor(x)) x else as.double(x), 
##     na.rm = na.rm))
body(sd)[1]
## sqrt()

dan kita bahkan dapat mengacaukannya (tanpa tujuan, dalam hal ini)

vals <- c(1, 3, 5, 7)
sd(vals)
## [1] 2.581989
my_sd <- sd
body(my_sd)[1] <- call("log")
my_sd # note that the function now (wrongly) uses log() instead of sqrt()
## function (x, na.rm = FALSE) 
## log(var(if (is.vector(x) || is.factor(x)) x else as.double(x), 
##     na.rm = na.rm))
## <environment: namespace:stats>
my_sd(vals)
## [1] 1.89712

Halaman Wikipedia mencantumkan contoh refleksi berikut di R

# Without reflection, assuming foo() returns an S3-type object that has method "hello"
obj <- foo()
hello(obj)

# With reflection
class_name <- "foo"
generic_having_foo_method <- "hello"
obj <- do.call(class_name, list())
do.call(generic_having_foo_method, alist(obj))

Gunakan objek dan kelas data yang lebih spesifik, mis tibble::tibble Dan summary Mungkin
lebih jelas

library(tibble) # do.call doesn't like pkg::fun as a string

# Without reflection
obj <- tibble(a = 1:2, b = 3:4)
summary(obj)
##        a              b       
##  Min.   :1.00   Min.   :3.00  
##  1st Qu.:1.25   1st Qu.:3.25  
##  Median :1.50   Median :3.50  
##  Mean   :1.50   Mean   :3.50  
##  3rd Qu.:1.75   3rd Qu.:3.75  
##  Max.   :2.00   Max.   :4.00
# With reflection
class_name <- "tibble"
generic_having_foo_method <- "summary"
obj <- do.call(class_name, list(a = 1:2, b = 3:4))
obj
## # A tibble: 2 × 2
##       a     b
##   <int> <int>
## 1     1     3
## 2     2     4
do.call(generic_having_foo_method, alist(obj))
##        a              b       
##  Min.   :1.00   Min.   :3.00  
##  1st Qu.:1.25   1st Qu.:3.25  
##  Median :1.50   Median :3.50  
##  Mean   :1.50   Mean   :3.50  
##  3rd Qu.:1.75   3rd Qu.:3.75  
##  Max.   :2.00   Max.   :4.00

Jadi mungkin lebih penting untuk bisa menggunakan string yang berisi “nama” dari
fungsi dan pergi dan temukan fungsi itu, atau hanya kemampuan untuk membuat fungsi
atas permintaan berdasarkan objek non-fungsional (?). Tolong, beri tahu saya jika ada lebih banyak
penjelasan yang mencerahkan.

Saya masih berpikir saya tidak mengerti semuanya (perlu lebih banyak waktu) tetapi saya membuat catatan
beberapa penelitian tambahan bahwa “refleksi” dan “makro” adalah dua konsep yang sangat mirip. Saat ini
makro Menjadi sesuatu yang setidaknya pernah saya dengar, jadi saya mulai melakukan penelitian lebih lanjut.

Sayangnya, pencarian web untuk istilah “cermin” dan “makro” banyak muncul
hasil fotografi lensa makro.

Saya pernah mendengar tentang makro di Julia yang digunakan untuk “menulis ulang” ekspresi. Ini daftar yang bagus
proses, serta dokumen resmi. itu adalah
digunakan di banyak tempat. Salah satu tempat yang berkembang adalah Tidier.jl yang diimplementasikan dengan rapi (setidaknya yang paling populer). dplyr Dan purrr bagian)
gunakan makro (diwakili oleh a @ awalan)

using Tidier
using RDatasets

movies = dataset("ggplot2", "movies");

@chain movies begin
    @mutate(Budget = Budget / 1_000_000)
    @filter(Budget >= mean(skipmissing(Budget)))
    @select(Title, Budget)
    @slice(1:5)
end

Rust menggunakan makro untuk mencetak (antara lain); println!() adalah makro,
tampaknya setidaknya sebagian karena harus bisa sewenang-wenang
jumlah argumen, sehingga seseorang dapat menulis

>> println!("a = {}, b = {}, c = {}", 1, 2, 3)
a = 1, b = 2, c = 3

Rust memiliki makro singkatan untuk membuat vektor baru vec!()

>> let v = vec![2, 3, 4];

dan juga “debug makro” dbg!()
ini sangat berguna – ini mencetak ekspresi yang Anda bungkus, ditambah nilainya, jadi
Anda dapat memeriksa status saat ini dengan contoh

>> dbg!(&v);
[src/lib.rs:109] &v = [
    2,
    3,
    4,
]

Yang terakhir ini akan bagus untuk dimiliki di R… sebagai catatan tambahan, kita bisa membuat a
versi sederhana dengan {rlang}

dbg <- function(x) {
  ex <- rlang::f_text(rlang::enquos(x)[[1]])
  ret <- rlang::eval_bare(x)
  message(glue::glue("DEBUG: {ex} = {ret}"))
  ret
}

a <- 1
b <- 3
x <- dbg(a + b)
## DEBUG: a + b = 4
y <- dbg(2*x + 3)
## DEBUG: 2 * x + 3 = 11
z <- 10 + dbg(y*2)
## DEBUG: y * 2 = 22

Dalam semua contoh makro ini, kodenya adalah berlari berbeda dari kode Anda menulis
karena makro membuat beberapa perubahan sebelum eksekusi.

Di R tidak ada cara yang “tepat” untuk melakukan ini selain kami MELAKUKAN Apakah ada cara untuk memanipulasi kode?
dan kita MELAKUKAN ada cara untuk mengambil input “tidak diurai”, misalnya: substitute(). Lihat sekilas
untuk “makro dalam R” membuat fungsi dalam paket yang berusia lebih dari 20 tahun (saya punya
baru mulai kuliah saat ini keluar dan tahu tentang 0 pemrograman) dan
disertai dengan artikel; gtools::defmacro() oleh Thomas Lumley
terstruktur untuk menulis sesuatu yang berperilaku seperti makro.

Artikel itu dari tahun 2001 ketika R 1.3.1 dirilis. Kode contoh membuat saya melakukannya dua kali

library(gtools)

####
# macro for replacing a specified missing value indicator with NA
# within a dataframe
###
setNA <- defmacro(df, var, values,
  expr = {
    df$var[df$var %in% values] <- NA
  }
)

# create example data using 999 as a missing value indicator
d <- data.frame(
  Grp = c("Trt", "Ctl", "Ctl", "Trt", "Ctl", "Ctl", "Trt", "Ctl", "Trt", "Ctl"),
  V1 = c(1, 2, 3, 4, 5, 6, 999, 8, 9, 10),
  V2 = c(1, 1, 1, 1, 1, 2, 999, 2, 999, 999),
  stringsAsFactors = TRUE
)
d
##    Grp  V1  V2
## 1  Trt   1   1
## 2  Ctl   2   1
## 3  Ctl   3   1
## 4  Trt   4   1
## 5  Ctl   5   1
## 6  Ctl   6   2
## 7  Trt 999 999
## 8  Ctl   8   2
## 9  Trt   9 999
## 10 Ctl  10 999
# Try it out
setNA(d, V1, 999)
setNA(d, V2, 999)
d
##    Grp V1 V2
## 1  Trt  1  1
## 2  Ctl  2  1
## 3  Ctl  3  1
## 4  Trt  4  1
## 5  Ctl  5  1
## 6  Ctl  6  2
## 7  Trt NA NA
## 8  Ctl  8  2
## 9  Trt  9 NA
## 10 Ctl 10 NA

Tunggu – saya pikir… tidak ada pencarian di baris terakhir itu, tapi datanya
sedang dimodifikasi!?! Tentu saja, internal dari defmacro memperjelas bahwa ini
adalah masalahnya, tapi sepertinya sihir. Pada dasarnya, ini mendefinisikan apa yang dibutuhkan
terjadi, apa yang perlu terjadi (melalui substitute()) dan mewujudkannya di parent.frame(). Ringkas! Jadi apa lagi yang bisa kita lakukan dengan ini?

Saya memikirkannya sebentar dan menyadari apa yang bisa terjadi [te|ho]hebat…

Beberapa minggu yang lalu, Danielle Navarro mengabulkan permintaan

bukan pertama kalinya saya berharap bahwa push() dan pop() adalah nama umum S3 di #rstats

Sekarang, jika Anda tidak terbiasa dengan mereka, pop(x) menghapus elemen pertama dari struktur x (mis. vektor) dan mengembalikan nilai pertama itu, meninggalkan objek aslinya x hanya berisi elemen yang tersisa, sementara push(x, y) masukkan nilai y adalah elemen pertama dari x, memindahkan elemen yang tersisa ke baris berikutnya. Mereka muncul lebih sering dalam bahasa berorientasi objek, tetapi mereka
tidak ada di R

Jika kita mendefinisikan vektor a mengandung beberapa nilai

a <- c(3, 1, 4, 1, 5, 9)

dan kami ingin mengekstraksi nilai pertama, kami pasti dapat melakukannya

a[1]
## [1] 3

tetapi, karena sifat R, vektor a konstan

a
## [1] 3 1 4 1 5 9

Sebagai gantinya, kita dapat membuang nilai pertama dari a dengan

a[-1]
## [1] 1 4 1 5 9

tapi lagi, a tetap tidak berubah – untuk memodifikasi a kita harus mendefinisikannya kembali sebagai contoh

a <- a[-1]
a
## [1] 1 4 1 5 9

Jika kita ingin membangun sebuah pop() fungsi, kami Mungkin menggunakan substitute() untuk mencari tahu
apa objek input yang diteruskan, lakukan ekstraksi elemen pertama, dll

Namun seperti yang baru saja kita lihat, ada cara yang lebih baik untuk mendefinisikannya – makro!

r_pop <- gtools::defmacro(x, expr = {
  ret <- x[1]
  x <- x[-1]
  ret
})

Sekarang, jika kita menggunakannya pada vektor

a <- c(3, 1, 4, 1, 5, 9)
r_pop(a)
## [1] 3
a
## [1] 1 4 1 5 9

Berhasil!!!

Namun, Danielle menginginkan Generik, jadi kami dapat melakukannya dengan mudah pop() Metode Generik dan Ekstra untuk
beberapa kelas (dapat diperpanjang lebih lanjut).

Terakhir, saya memperkenalkan paket yang benar-benar baru; {rubah}

pop() pergi {musang}

pop() pergi {musang}

Ini mendefinisikan pop() Dan push() sebagai Generik dengan metode yang ditentukan untuk vectorS, listpasir data.frameS

a <- list(x = c(2, 3), y = c("foo", "bar"), z = c(3.1, 4.2, 6.9))
a
## $x
## [1] 2 3
## 
## $y
## [1] "foo" "bar"
## 
## $z
## [1] 3.1 4.2 6.9
x <- pop(a)
a
## $y
## [1] "foo" "bar"
## 
## $z
## [1] 3.1 4.2 6.9
x
## [1] 2 3
a <- data.frame(x = c(2, 3, 4), y = c("foo", "bar", "baz"), z = c(3.1, 4.2, 6.9))
a
##   x   y   z
## 1 2 foo 3.1
## 2 3 bar 4.2
## 3 4 baz 6.9
x <- pop(a)
a
##   x   y   z
## 2 3 bar 4.2
## 3 4 baz 6.9
x
##   x   y   z
## 1 2 foo 3.1
a <- c(1, 4, 1, 5, 9)
a
## [1] 1 4 1 5 9
push(a, 3)
a
## [1] 3 1 4 1 5 9
a <- data.frame(y = c("foo", "bar", "baz"), z = c(3.1, 4.2, 6.9))
a
##     y   z
## 1 foo 3.1
## 2 bar 4.2
## 3 baz 6.9
push(a, data.frame(y = 99, z = 77))
a
##     y    z
## 1  99 77.0
## 2 foo  3.1
## 3 bar  4.2
## 4 baz  6.9

Saya menulis paket (sederhana) ini sebagai latihan kecil – saya benar-benar tidak berpikir Anda
benar-benar harus menggunakannya untuk apa pun. Itu “Sepertinya dimodifikasi di tempat tapi sebenarnya
Tidak”
benar-benar bukan idiom untuk R. Namun, saya sangat ingin melihat
itu defmacro dapat digunakan sebagai definisi fungsi yang akan dihormati oleh operator. Satu-satunya masalah yang saya temukan sejauh ini adalah saya tidak dapat menggunakan elips (...) dalam tanda tangan fungsi.

Saya perhatikan bahwa Dirk Schumacher membuat a defmacro paket yang lebih baru, tapi itu muncul
dimaksudkan untuk lebih dari membangun makro yang diperluas saat paket dimuat (menariknya, “makro waktu kompilasi” – kami telah membahasnya secara lengkap). Ini sepertinya peluang bagus untuk “inline”
beberapa fungsi. Saya pasti akan menggali lebih dalam tentang itu.

Beri tahu saya jika Anda memiliki penjelasan yang lebih baik tentang salah satu konsep yang telah saya jelaskan (dengan buruk) di sini;
Saya murni belajar dan mengikuti saran Julia Evans tentang blogging.

devtools::session_info()
## ─ Session info ───────────────────────────────────────────────────────────────
##  setting  value
##  version  R version 4.1.2 (2021-11-01)
##  os       Pop!_OS 22.04 LTS
##  system   x86_64, linux-gnu
##  ui       X11
##  language (EN)
##  collate  en_AU.UTF-8
##  ctype    en_AU.UTF-8
##  tz       Australia/Adelaide
##  date     2023-06-10
##  pandoc   3.1.1 @ /usr/lib/rstudio/resources/app/bin/quarto/bin/tools/ (via rmarkdown)
## 
## ─ Packages ───────────────────────────────────────────────────────────────────
##  package     * version date (UTC) lib source
##  blogdown      1.17    2023-05-16 [1] CRAN (R 4.1.2)
##  bookdown      0.29    2022-09-12 [1] CRAN (R 4.1.2)
##  bslib         0.4.1   2022-11-02 [3] CRAN (R 4.2.2)
##  cachem        1.0.6   2021-08-19 [3] CRAN (R 4.2.0)
##  callr         3.7.3   2022-11-02 [3] CRAN (R 4.2.2)
##  cli           3.4.1   2022-09-23 [3] CRAN (R 4.2.1)
##  crayon        1.5.2   2022-09-29 [3] CRAN (R 4.2.1)
##  devtools      2.4.5   2022-10-11 [1] CRAN (R 4.1.2)
##  digest        0.6.30  2022-10-18 [3] CRAN (R 4.2.1)
##  ellipsis      0.3.2   2021-04-29 [3] CRAN (R 4.1.1)
##  evaluate      0.18    2022-11-07 [3] CRAN (R 4.2.2)
##  fansi         1.0.3   2022-03-24 [3] CRAN (R 4.2.0)
##  fastmap       1.1.0   2021-01-25 [3] CRAN (R 4.2.0)
##  fs            1.5.2   2021-12-08 [3] CRAN (R 4.1.2)
##  glue          1.6.2   2022-02-24 [3] CRAN (R 4.2.0)
##  gtools      * 3.9.4   2022-11-27 [1] CRAN (R 4.1.2)
##  htmltools     0.5.3   2022-07-18 [3] CRAN (R 4.2.1)
##  htmlwidgets   1.5.4   2021-09-08 [1] CRAN (R 4.1.2)
##  httpuv        1.6.6   2022-09-08 [1] CRAN (R 4.1.2)
##  jquerylib     0.1.4   2021-04-26 [3] CRAN (R 4.1.2)
##  jsonlite      1.8.3   2022-10-21 [3] CRAN (R 4.2.1)
##  knitr         1.40    2022-08-24 [3] CRAN (R 4.2.1)
##  later         1.3.0   2021-08-18 [1] CRAN (R 4.1.2)
##  lifecycle     1.0.3   2022-10-07 [3] CRAN (R 4.2.1)
##  magrittr      2.0.3   2022-03-30 [3] CRAN (R 4.2.0)
##  memoise       2.0.1   2021-11-26 [3] CRAN (R 4.2.0)
##  mime          0.12    2021-09-28 [3] CRAN (R 4.2.0)
##  miniUI        0.1.1.1 2018-05-18 [1] CRAN (R 4.1.2)
##  pillar        1.8.1   2022-08-19 [3] CRAN (R 4.2.1)
##  pkgbuild      1.3.1   2021-12-20 [1] CRAN (R 4.1.2)
##  pkgconfig     2.0.3   2019-09-22 [3] CRAN (R 4.0.1)
##  pkgload       1.3.0   2022-06-27 [1] CRAN (R 4.1.2)
##  prettyunits   1.1.1   2020-01-24 [3] CRAN (R 4.0.1)
##  processx      3.8.0   2022-10-26 [3] CRAN (R 4.2.1)
##  profvis       0.3.7   2020-11-02 [1] CRAN (R 4.1.2)
##  promises      1.2.0.1 2021-02-11 [1] CRAN (R 4.1.2)
##  ps            1.7.2   2022-10-26 [3] CRAN (R 4.2.2)
##  purrr         1.0.1   2023-01-10 [1] CRAN (R 4.1.2)
##  R6            2.5.1   2021-08-19 [3] CRAN (R 4.2.0)
##  Rcpp          1.0.9   2022-07-08 [1] CRAN (R 4.1.2)
##  remotes       2.4.2   2021-11-30 [1] CRAN (R 4.1.2)
##  rlang         1.0.6   2022-09-24 [1] CRAN (R 4.1.2)
##  rmarkdown     2.18    2022-11-09 [3] CRAN (R 4.2.2)
##  rstudioapi    0.14    2022-08-22 [3] CRAN (R 4.2.1)
##  sass          0.4.2   2022-07-16 [3] CRAN (R 4.2.1)
##  sessioninfo   1.2.2   2021-12-06 [1] CRAN (R 4.1.2)
##  shiny         1.7.2   2022-07-19 [1] CRAN (R 4.1.2)
##  stringi       1.7.8   2022-07-11 [3] CRAN (R 4.2.1)
##  stringr       1.5.0   2022-12-02 [1] CRAN (R 4.1.2)
##  tibble      * 3.1.8   2022-07-22 [3] CRAN (R 4.2.2)
##  urlchecker    1.0.1   2021-11-30 [1] CRAN (R 4.1.2)
##  usethis       2.1.6   2022-05-25 [1] CRAN (R 4.1.2)
##  utf8          1.2.2   2021-07-24 [3] CRAN (R 4.2.0)
##  vctrs         0.5.2   2023-01-23 [1] CRAN (R 4.1.2)
##  weasel      * 0.1.0   2023-06-09 [1] local
##  xfun          0.34    2022-10-18 [3] CRAN (R 4.2.1)
##  xtable        1.8-4   2019-04-21 [1] CRAN (R 4.1.2)
##  yaml          2.3.6   2022-10-18 [3] CRAN (R 4.2.1)
## 
##  [1] /home/jono/R/x86_64-pc-linux-gnu-library/4.1
##  [2] /usr/local/lib/R/site-library
##  [3] /usr/lib/R/site-library
##  [4] /usr/lib/R/library
## 
## ──────────────────────────────────────────────────────────────────────────────

Software Terbaru Saat Ini



Aplikasi yang sedang trend saat ini

object oriented programming, programming language, programming adalah, web programming, belajar programming, tournament software, software, software adalah, contoh software, apa itu software, pengertian software, aplikasi, aplikasi penghasil uang, aplikasi bokep, aplikasi video, programming

#Merefleksikan #Makro #juliablogger.com

Tinggalkan Balasan

Alamat email Anda tidak akan dipublikasikan. Ruas yang wajib ditandai *